Commit e413a806 by David Hotham Committed by GitHub

Additional typechecking fixes (#4755)

* new FIXME: are nameless repositories desired/expected?

* new TODO: should the LegacyRepository really inherit from the PyPiRepository?
parent a434e7ef
...@@ -13,7 +13,7 @@ warn_unused_configs = True ...@@ -13,7 +13,7 @@ warn_unused_configs = True
# should be added to this whitelist. # should be added to this whitelist.
# see https://github.com/python-poetry/poetry/pull/4510. # see https://github.com/python-poetry/poetry/pull/4510.
[mypy-poetry.config.*] [mypy-poetry.config.file_config_source]
ignore_errors = True ignore_errors = True
[mypy-poetry.console.*] [mypy-poetry.console.*]
...@@ -34,16 +34,13 @@ ignore_errors = True ...@@ -34,16 +34,13 @@ ignore_errors = True
[mypy-poetry.mixology.*] [mypy-poetry.mixology.*]
ignore_errors = True ignore_errors = True
[mypy-poetry.packages.*] [mypy-poetry.packages.locker]
ignore_errors = True
[mypy-poetry.publishing.*]
ignore_errors = True ignore_errors = True
[mypy-poetry.puzzle.*] [mypy-poetry.puzzle.*]
ignore_errors = True ignore_errors = True
[mypy-poetry.repositories.*] [mypy-poetry.repositories.installed_repository]
ignore_errors = True ignore_errors = True
[mypy-poetry.utils.*] [mypy-poetry.utils.*]
......
...@@ -14,9 +14,6 @@ from .config_source import ConfigSource ...@@ -14,9 +14,6 @@ from .config_source import ConfigSource
from .dict_config_source import DictConfigSource from .dict_config_source import DictConfigSource
_NOT_SET = object()
def boolean_validator(val: str) -> bool: def boolean_validator(val: str) -> bool:
return val in {"true", "false", "1", "0"} return val in {"true", "false", "1", "0"}
...@@ -27,7 +24,7 @@ def boolean_normalizer(val: str) -> bool: ...@@ -27,7 +24,7 @@ def boolean_normalizer(val: str) -> bool:
class Config: class Config:
default_config = { default_config: Dict[str, Any] = {
"cache-dir": str(CACHE_DIR), "cache-dir": str(CACHE_DIR),
"virtualenvs": { "virtualenvs": {
"create": True, "create": True,
...@@ -45,12 +42,8 @@ class Config: ...@@ -45,12 +42,8 @@ class Config:
self._config = deepcopy(self.default_config) self._config = deepcopy(self.default_config)
self._use_environment = use_environment self._use_environment = use_environment
self._base_dir = base_dir self._base_dir = base_dir
self._config_source = DictConfigSource() self._config_source: ConfigSource = DictConfigSource()
self._auth_config_source = DictConfigSource() self._auth_config_source: ConfigSource = DictConfigSource()
@property
def name(self) -> str:
return str(self._file.path)
@property @property
def config(self) -> Dict: def config(self) -> Dict:
...@@ -114,9 +107,9 @@ class Config: ...@@ -114,9 +107,9 @@ class Config:
env = "POETRY_{}".format( env = "POETRY_{}".format(
"_".join(k.upper().replace("-", "_") for k in keys) "_".join(k.upper().replace("-", "_") for k in keys)
) )
value = os.getenv(env, _NOT_SET) env_value = os.getenv(env)
if value is not _NOT_SET: if env_value is not None:
return self.process(self._get_normalizer(setting_name)(value)) return self.process(self._get_normalizer(setting_name)(env_value))
value = self._config value = self._config
for key in keys: for key in keys:
......
...@@ -6,7 +6,7 @@ from .config_source import ConfigSource ...@@ -6,7 +6,7 @@ from .config_source import ConfigSource
class DictConfigSource(ConfigSource): class DictConfigSource(ConfigSource):
def __init__(self) -> None: def __init__(self) -> None:
self._config = {} self._config: Dict[str, Any] = {}
@property @property
def config(self) -> Dict[str, Any]: def config(self) -> Dict[str, Any]:
......
...@@ -59,7 +59,7 @@ class PackageInfo: ...@@ -59,7 +59,7 @@ class PackageInfo:
platform: Optional[str] = None, platform: Optional[str] = None,
requires_dist: Optional[List[str]] = None, requires_dist: Optional[List[str]] = None,
requires_python: Optional[str] = None, requires_python: Optional[str] = None,
files: Optional[List[str]] = None, files: Optional[List[Dict[str, str]]] = None,
cache_version: Optional[str] = None, cache_version: Optional[str] = None,
): ):
self.name = name self.name = name
......
...@@ -21,5 +21,3 @@ class ProjectPackage(_ProjectPackage): ...@@ -21,5 +21,3 @@ class ProjectPackage(_ProjectPackage):
else: else:
self._version = version self._version = version
self._pretty_version = pretty_version or version.text self._pretty_version = pretty_version or version.text
return self
...@@ -44,7 +44,7 @@ class Publisher: ...@@ -44,7 +44,7 @@ class Publisher:
password: Optional[str], password: Optional[str],
cert: Optional[Path] = None, cert: Optional[Path] = None,
client_cert: Optional[Path] = None, client_cert: Optional[Path] = None,
dry_run: Optional[bool] = False, dry_run: bool = False,
) -> None: ) -> None:
if not repository_name: if not repository_name:
url = "https://upload.pypi.org/legacy/" url = "https://upload.pypi.org/legacy/"
......
...@@ -57,8 +57,8 @@ class Uploader: ...@@ -57,8 +57,8 @@ class Uploader:
self._poetry = poetry self._poetry = poetry
self._package = poetry.package self._package = poetry.package
self._io = io self._io = io
self._username = None self._username: Optional[str] = None
self._password = None self._password: Optional[str] = None
@property @property
def user_agent(self) -> str: def user_agent(self) -> str:
...@@ -89,14 +89,15 @@ class Uploader: ...@@ -89,14 +89,15 @@ class Uploader:
return sorted(wheels + tars) 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._username = username
self._password = password self._password = password
def make_session(self) -> requests.Session: def make_session(self) -> requests.Session:
session = requests.session() session = requests.session()
if self.is_authenticated(): auth = self.get_auth()
session.auth = (self._username, self._password) if auth is not None:
session.auth = auth
session.headers["User-Agent"] = self.user_agent session.headers["User-Agent"] = self.user_agent
for scheme in ("http://", "https://"): for scheme in ("http://", "https://"):
...@@ -104,8 +105,11 @@ class Uploader: ...@@ -104,8 +105,11 @@ class Uploader:
return session return session
def is_authenticated(self) -> bool: def get_auth(self) -> Optional[Tuple[str, str]]:
return self._username is not None and self._password is not None if self._username is None or self._password is None:
return None
return (self._username, self._password)
def upload( def upload(
self, self,
...@@ -147,16 +151,15 @@ class Uploader: ...@@ -147,16 +151,15 @@ class Uploader:
md5_digest = md5_hash.hexdigest() md5_digest = md5_hash.hexdigest()
sha2_digest = sha256_hash.hexdigest() sha2_digest = sha256_hash.hexdigest()
blake2_256_digest: Optional[str] = None
if _has_blake2: if _has_blake2:
blake2_256_digest = blake2_256_hash.hexdigest() blake2_256_digest = blake2_256_hash.hexdigest()
else:
blake2_256_digest = None
py_version: Optional[str] = None
if file_type == "bdist_wheel": if file_type == "bdist_wheel":
wheel_info = wheel_file_re.match(file.name) wheel_info = wheel_file_re.match(file.name)
py_version = wheel_info.group("pyver") if wheel_info is not None:
else: py_version = wheel_info.group("pyver")
py_version = None
data = { data = {
# identify release # identify release
...@@ -231,7 +234,7 @@ class Uploader: ...@@ -231,7 +234,7 @@ class Uploader:
} }
) )
data_to_send = self._prepare_data(data) data_to_send: List[Tuple[str, Any]] = self._prepare_data(data)
with file.open("rb") as fp: with file.open("rb") as fp:
data_to_send.append( data_to_send.append(
...@@ -256,7 +259,7 @@ class Uploader: ...@@ -256,7 +259,7 @@ class Uploader:
allow_redirects=False, allow_redirects=False,
headers={"Content-Type": monitor.content_type}, 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( bar.set_format(
f" - Uploading <c1>{file.name}</c1> <fg=green>%percent%%</>" f" - Uploading <c1>{file.name}</c1> <fg=green>%percent%%</>"
) )
......
...@@ -10,22 +10,22 @@ if TYPE_CHECKING: ...@@ -10,22 +10,22 @@ if TYPE_CHECKING:
class BaseRepository: class BaseRepository:
def __init__(self) -> None: def __init__(self) -> None:
self._packages = [] self._packages: List[Package] = []
@property @property
def packages(self) -> List["Package"]: def packages(self) -> List["Package"]:
return self._packages return self._packages
def has_package(self, package: "Package") -> None: def has_package(self, package: "Package") -> bool:
raise NotImplementedError() raise NotImplementedError()
def package( def package(
self, name: str, version: str, extras: Optional[List[str]] = None self, name: str, version: str, extras: Optional[List[str]] = None
) -> None: ) -> "Package":
raise NotImplementedError() raise NotImplementedError()
def find_packages(self, dependency: "Dependency") -> None: def find_packages(self, dependency: "Dependency") -> List["Package"]:
raise NotImplementedError() raise NotImplementedError()
def search(self, query: str) -> None: def search(self, query: str) -> List["Package"]:
raise NotImplementedError() raise NotImplementedError()
...@@ -5,6 +5,7 @@ import urllib.parse ...@@ -5,6 +5,7 @@ import urllib.parse
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from html import unescape
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any from typing import Any
...@@ -12,6 +13,7 @@ from typing import Dict ...@@ -12,6 +13,7 @@ from typing import Dict
from typing import Iterator from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
from urllib.parse import quote
import requests import requests
import requests.auth import requests.auth
...@@ -43,23 +45,6 @@ from .pypi_repository import PyPiRepository ...@@ -43,23 +45,6 @@ from .pypi_repository import PyPiRepository
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency 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(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
import html5lib import html5lib
...@@ -164,6 +149,8 @@ class Page: ...@@ -164,6 +149,8 @@ class Page:
return self._clean_re.sub(lambda match: "%%%2x" % ord(match.group(0)), url) return self._clean_re.sub(lambda match: "%%%2x" % ord(match.group(0)), url)
# TODO: revisit whether the LegacyRepository should inherit from PyPiRepository.
# <https://github.com/python-poetry/poetry/pull/4755#discussion_r748865374>.
class LegacyRepository(PyPiRepository): class LegacyRepository(PyPiRepository):
def __init__( def __init__(
self, self,
...@@ -269,7 +256,7 @@ class LegacyRepository(PyPiRepository): ...@@ -269,7 +256,7 @@ class LegacyRepository(PyPiRepository):
if self._cache.store("matches").has(key): if self._cache.store("matches").has(key):
versions = self._cache.store("matches").get(key) versions = self._cache.store("matches").get(key)
else: else:
page = self._get("/{}/".format(dependency.name.replace(".", "-"))) page = self._get_page("/{}/".format(dependency.name.replace(".", "-")))
if page is None: if page is None:
return [] return []
...@@ -338,14 +325,14 @@ class LegacyRepository(PyPiRepository): ...@@ -338,14 +325,14 @@ class LegacyRepository(PyPiRepository):
return package return package
def find_links_for_package(self, package: Package) -> List[Link]: 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: if page is None:
return [] return []
return list(page.links_for_version(package.version)) return list(page.links_for_version(package.version))
def _get_release_info(self, name: str, version: str) -> dict: 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: if page is None:
raise PackageNotFound(f'No package named "{name}"') raise PackageNotFound(f'No package named "{name}"')
...@@ -419,7 +406,7 @@ class LegacyRepository(PyPiRepository): ...@@ -419,7 +406,7 @@ class LegacyRepository(PyPiRepository):
return data.asdict() return data.asdict()
def _get(self, endpoint: str) -> Optional[Page]: def _get_page(self, endpoint: str) -> Optional[Page]:
url = self._url + endpoint url = self._url + endpoint
try: try:
response = self.session.get(url) response = self.session.get(url)
......
...@@ -22,11 +22,11 @@ class Pool(BaseRepository): ...@@ -22,11 +22,11 @@ class Pool(BaseRepository):
if repositories is None: if repositories is None:
repositories = [] repositories = []
self._lookup: Dict[str, int] = {} self._lookup: Dict[Optional[str], int] = {}
self._repositories: List[Repository] = [] self._repositories: List[Repository] = []
self._default = False self._default = False
self._has_primary_repositories = False self._has_primary_repositories = False
self._secondary_start_idx = None self._secondary_start_idx: Optional[int] = None
for repository in repositories: for repository in repositories:
self.add_repository(repository) self.add_repository(repository)
...@@ -65,6 +65,8 @@ class Pool(BaseRepository): ...@@ -65,6 +65,8 @@ class Pool(BaseRepository):
""" """
Adds a repository to the pool. 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 = (
repository.name.lower() if repository.name is not None else None repository.name.lower() if repository.name is not None else None
) )
......
...@@ -24,7 +24,7 @@ class Repository(BaseRepository): ...@@ -24,7 +24,7 @@ class Repository(BaseRepository):
self.add_package(package) self.add_package(package)
@property @property
def name(self) -> str: def name(self) -> Optional[str]:
return self._name return self._name
def package( def package(
......
...@@ -28,7 +28,7 @@ class MockRepository(LegacyRepository): ...@@ -28,7 +28,7 @@ class MockRepository(LegacyRepository):
"legacy", url="http://legacy.foo.bar", disable_cache=True "legacy", url="http://legacy.foo.bar", disable_cache=True
) )
def _get(self, endpoint): def _get_page(self, endpoint):
parts = endpoint.split("/") parts = endpoint.split("/")
name = parts[1] name = parts[1]
...@@ -49,7 +49,7 @@ class MockRepository(LegacyRepository): ...@@ -49,7 +49,7 @@ class MockRepository(LegacyRepository):
def test_page_relative_links_path_are_correct(): def test_page_relative_links_path_are_correct():
repo = MockRepository() repo = MockRepository()
page = repo._get("/relative") page = repo._get_page("/relative")
for link in page.links: for link in page.links:
assert link.netloc == "legacy.foo.bar" assert link.netloc == "legacy.foo.bar"
...@@ -59,7 +59,7 @@ def test_page_relative_links_path_are_correct(): ...@@ -59,7 +59,7 @@ def test_page_relative_links_path_are_correct():
def test_page_absolute_links_path_are_correct(): def test_page_absolute_links_path_are_correct():
repo = MockRepository() repo = MockRepository()
page = repo._get("/absolute") page = repo._get_page("/absolute")
for link in page.links: for link in page.links:
assert link.netloc == "files.pythonhosted.org" assert link.netloc == "files.pythonhosted.org"
...@@ -68,7 +68,7 @@ def test_page_absolute_links_path_are_correct(): ...@@ -68,7 +68,7 @@ def test_page_absolute_links_path_are_correct():
def test_sdist_format_support(): def test_sdist_format_support():
repo = MockRepository() repo = MockRepository()
page = repo._get("/relative") page = repo._get_page("/relative")
bz2_links = list(filter(lambda link: link.ext == ".tar.bz2", page.links)) bz2_links = list(filter(lambda link: link.ext == ".tar.bz2", page.links))
assert len(bz2_links) == 1 assert len(bz2_links) == 1
assert bz2_links[0].filename == "poetry-0.1.1.tar.bz2" assert bz2_links[0].filename == "poetry-0.1.1.tar.bz2"
...@@ -335,21 +335,21 @@ class MockHttpRepository(LegacyRepository): ...@@ -335,21 +335,21 @@ class MockHttpRepository(LegacyRepository):
def test_get_200_returns_page(http): def test_get_200_returns_page(http):
repo = MockHttpRepository({"/foo": 200}, http) repo = MockHttpRepository({"/foo": 200}, http)
assert repo._get("/foo") assert repo._get_page("/foo")
@pytest.mark.parametrize("status_code", [401, 403, 404]) @pytest.mark.parametrize("status_code", [401, 403, 404])
def test_get_40x_and_returns_none(http, status_code): def test_get_40x_and_returns_none(http, status_code):
repo = MockHttpRepository({"/foo": status_code}, http) 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): def test_get_5xx_raises(http):
repo = MockHttpRepository({"/foo": 500}, http) repo = MockHttpRepository({"/foo": 500}, http)
with pytest.raises(RepositoryError): with pytest.raises(RepositoryError):
repo._get("/foo") repo._get_page("/foo")
def test_get_redirected_response_url(http, monkeypatch): def test_get_redirected_response_url(http, monkeypatch):
...@@ -363,4 +363,4 @@ def test_get_redirected_response_url(http, monkeypatch): ...@@ -363,4 +363,4 @@ def test_get_redirected_response_url(http, monkeypatch):
return response return response
monkeypatch.setattr(repo.session, "get", get_mock) 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/"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment