Commit cddd6759 by finswimmer Committed by GitHub

convert type comments to type hints (#3638)

parent 18a9e2df
......@@ -19,11 +19,11 @@ from .dict_config_source import DictConfigSource
_NOT_SET = object()
def boolean_validator(val): # type: (str) -> bool
def boolean_validator(val: str) -> bool:
return val in {"true", "false", "1", "0"}
def boolean_normalizer(val): # type: (str) -> bool
def boolean_normalizer(val: str) -> bool:
return val in ["true", "1"]
......@@ -42,8 +42,8 @@ class Config(object):
}
def __init__(
self, use_environment=True, base_dir=None
): # type: (bool, Optional[Path]) -> None
self, use_environment: bool = True, base_dir: Optional[Path] = None
) -> None:
self._config = deepcopy(self.default_config)
self._use_environment = use_environment
self._base_dir = base_dir
......@@ -51,38 +51,38 @@ class Config(object):
self._auth_config_source = DictConfigSource()
@property
def name(self): # type: () -> str
def name(self) -> str:
return str(self._file.path)
@property
def config(self): # type: () -> Dict
def config(self) -> Dict:
return self._config
@property
def config_source(self): # type: () -> ConfigSource
def config_source(self) -> ConfigSource:
return self._config_source
@property
def auth_config_source(self): # type: () -> ConfigSource
def auth_config_source(self) -> ConfigSource:
return self._auth_config_source
def set_config_source(self, config_source): # type: (ConfigSource) -> Config
def set_config_source(self, config_source: ConfigSource) -> "Config":
self._config_source = config_source
return self
def set_auth_config_source(self, config_source): # type: (ConfigSource) -> Config
def set_auth_config_source(self, config_source: ConfigSource) -> "Config":
self._auth_config_source = config_source
return self
def merge(self, config): # type: (Dict[str, Any]) -> None
def merge(self, config: Dict[str, Any]) -> None:
from poetry.utils.helpers import merge_dicts
merge_dicts(self._config, config)
def all(self): # type: () -> Dict[str, Any]
def _all(config, parent_key=""): # type: (Dict, str) -> Dict
def all(self) -> Dict[str, Any]:
def _all(config: Dict, parent_key: str = "") -> Dict:
all_ = {}
for key in config:
......@@ -101,10 +101,10 @@ class Config(object):
return _all(self.config)
def raw(self): # type: () -> Dict[str, Any]
def raw(self) -> Dict[str, Any]:
return self._config
def get(self, setting_name, default=None): # type: (str, Any) -> Any
def get(self, setting_name: str, default: Any = None) -> Any:
"""
Retrieve a setting value.
"""
......@@ -129,13 +129,13 @@ class Config(object):
return self.process(value)
def process(self, value): # type: (Any) -> Any
def process(self, value: Any) -> Any:
if not isinstance(value, str):
return value
return re.sub(r"{(.+?)}", lambda m: self.get(m.group(1)), value)
def _get_normalizer(self, name): # type: (str) -> Callable
def _get_normalizer(self, name: str) -> Callable:
if name in {
"virtualenvs.create",
"virtualenvs.in-project",
......
......@@ -2,8 +2,8 @@ from typing import Any
class ConfigSource(object):
def add_property(self, key, value): # type: (str, Any) -> None
def add_property(self, key: str, value: Any) -> None:
raise NotImplementedError()
def remove_property(self, key): # type: (str) -> None
def remove_property(self, key: str) -> None:
raise NotImplementedError()
......@@ -5,14 +5,14 @@ from .config_source import ConfigSource
class DictConfigSource(ConfigSource):
def __init__(self): # type: () -> None
def __init__(self) -> None:
self._config = {}
@property
def config(self): # type: () -> Dict[str, Any]
def config(self) -> Dict[str, Any]:
return self._config
def add_property(self, key, value): # type: (str, Any) -> None
def add_property(self, key: str, value: Any) -> None:
keys = key.split(".")
config = self._config
......@@ -26,7 +26,7 @@ class DictConfigSource(ConfigSource):
config = config[key]
def remove_property(self, key): # type: (str) -> None
def remove_property(self, key: str) -> None:
keys = key.split(".")
config = self._config
......
from contextlib import contextmanager
from typing import TYPE_CHECKING
from typing import Any
from typing import Generator
from typing import Iterator
from tomlkit import document
from tomlkit import table
......@@ -10,25 +10,25 @@ from .config_source import ConfigSource
if TYPE_CHECKING:
from tomlkit.toml_document import TOMLDocument # noqa
from tomlkit.toml_document import TOMLDocument
from poetry.core.toml.file import TOMLFile # noqa
from poetry.core.toml.file import TOMLFile
class FileConfigSource(ConfigSource):
def __init__(self, file, auth_config=False): # type: ("TOMLFile", bool) -> None
def __init__(self, file: "TOMLFile", auth_config: bool = False) -> None:
self._file = file
self._auth_config = auth_config
@property
def name(self): # type: () -> str
def name(self) -> str:
return str(self._file.path)
@property
def file(self): # type: () -> "TOMLFile"
def file(self) -> "TOMLFile":
return self._file
def add_property(self, key, value): # type: (str, Any) -> None
def add_property(self, key: str, value: Any) -> None:
with self.secure() as config:
keys = key.split(".")
......@@ -42,7 +42,7 @@ class FileConfigSource(ConfigSource):
config = config[key]
def remove_property(self, key): # type: (str) -> None
def remove_property(self, key: str) -> None:
with self.secure() as config:
keys = key.split(".")
......@@ -59,7 +59,7 @@ class FileConfigSource(ConfigSource):
current_config = current_config[key]
@contextmanager
def secure(self): # type: () -> Generator["TOMLDocument"]
def secure(self) -> Iterator["TOMLDocument"]:
if self.file.exists():
initial_config = self.file.read()
config = self.file.read()
......
......@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Optional
from typing import Type
from typing import cast
from cleo.application import Application as BaseApplication
......@@ -26,7 +27,7 @@ from .commands.command import Command
def load_command(name: str) -> Callable:
def _load():
def _load() -> Type[Command]:
module = import_module(
"poetry.console.commands.{}".format(".".join(name.split(" ")))
)
......@@ -75,7 +76,7 @@ COMMANDS = [
if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa
from poetry.poetry import Poetry
class Application(BaseApplication):
......@@ -220,7 +221,7 @@ class Application(BaseApplication):
logger.setLevel(level)
def set_env(self, event: ConsoleCommandEvent, event_name: str, _: Any):
def set_env(self, event: ConsoleCommandEvent, event_name: str, _: Any) -> None:
from .commands.env_command import EnvCommand
command: EnvCommand = cast(EnvCommand, event.command)
......@@ -272,7 +273,7 @@ class Application(BaseApplication):
command.set_installer(installer)
def main():
def main() -> int:
return Application().run()
......
......@@ -7,7 +7,7 @@ class AboutCommand(Command):
description = "Shows information about Poetry."
def handle(self): # type: () -> None
def handle(self) -> None:
self.line(
"""<info>Poetry - Package Management for Python</info>
......
......@@ -68,7 +68,7 @@ class AddCommand(InstallerCommand, InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> int
def handle(self) -> int:
from tomlkit import inline_table
from poetry.core.semver import parse_constraint
......@@ -192,8 +192,8 @@ class AddCommand(InstallerCommand, InitCommand):
return status
def get_existing_packages_from_input(
self, packages, poetry_content, target_section
): # type: (List[str], Dict, str) -> List[str]
self, packages: List[str], poetry_content: Dict, target_section: str
) -> List[str]:
existing_packages = []
for name in packages:
......@@ -203,9 +203,7 @@ class AddCommand(InstallerCommand, InitCommand):
return existing_packages
def notify_about_existing_packages(
self, existing_packages
): # type: (List[str]) -> None
def notify_about_existing_packages(self, existing_packages: List[str]) -> None:
self.line(
"The following packages are already present in the pyproject.toml and will be skipped:\n"
)
......
......@@ -18,7 +18,7 @@ class BuildCommand(EnvCommand):
"poetry.core.masonry.builders.wheel",
]
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.core.masonry import Builder
fmt = "all"
......
......@@ -14,7 +14,7 @@ class CacheClearCommand(Command):
arguments = [argument("cache", description="The name of the cache to clear.")]
options = [option("all", description="Clear all entries in the cache.")]
def handle(self): # type: () -> int
def handle(self) -> int:
from cachy import CacheManager
from poetry.locations import REPOSITORY_CACHE_DIR
......
......@@ -10,7 +10,7 @@ class CacheListCommand(Command):
name = "cache list"
description = "List Poetry's caches."
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from poetry.locations import REPOSITORY_CACHE_DIR
if os.path.exists(str(REPOSITORY_CACHE_DIR)):
......
......@@ -11,7 +11,7 @@ class CheckCommand(Command):
name = "check"
description = "Checks the validity of the <comment>pyproject.toml</comment> file."
def handle(self): # type: () -> int
def handle(self) -> int:
# Load poetry config and display errors, if any
poetry_file = Factory.locate(Path.cwd())
config = PyProjectTOML(poetry_file).poetry_config
......
......@@ -4,16 +4,19 @@ from cleo.commands.command import Command as BaseCommand
if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa
from poetry.console.application import Application
from poetry.poetry import Poetry
class Command(BaseCommand):
loggers = []
@property
def poetry(self): # type: () -> "Poetry"
return self.application.poetry
def poetry(self) -> "Poetry":
return self.get_application().poetry
def get_application(self) -> "Application":
return self.application
def reset_poetry(self): # type: () -> None
self.application.reset_poetry()
def reset_poetry(self) -> None:
self.get_application().reset_poetry()
......@@ -19,7 +19,7 @@ from .command import Command
if TYPE_CHECKING:
from poetry.config.config_source import ConfigSource # noqa
from poetry.config.config_source import ConfigSource
class ConfigCommand(Command):
......@@ -51,7 +51,7 @@ To remove a repository (repo is a short alias for repositories):
LIST_PROHIBITED_SETTINGS = {"http-basic", "pypi-token"}
@property
def unique_config_values(self): # type: () -> Dict[str, Tuple[Any, Any, Any]]
def unique_config_values(self) -> Dict[str, Tuple[Any, Any, Any]]:
from pathlib import Path
from poetry.config.config import boolean_normalizer
......@@ -90,7 +90,7 @@ To remove a repository (repo is a short alias for repositories):
return unique_config_values
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from pathlib import Path
from poetry.config.file_config_source import FileConfigSource
......@@ -269,8 +269,12 @@ To remove a repository (repo is a short alias for repositories):
raise ValueError("Setting {} does not exist".format(self.argument("key")))
def _handle_single_value(
self, source, key, callbacks, values
): # type: ("ConfigSource", str, Tuple[Any, Any, Any], List[Any]) -> int
self,
source: "ConfigSource",
key: str,
callbacks: Tuple[Any, Any, Any],
values: List[Any],
) -> int:
validator, normalizer, _ = callbacks
if len(values) > 1:
......@@ -284,7 +288,7 @@ To remove a repository (repo is a short alias for repositories):
return 0
def _list_configuration(self, config, raw, k=""): # type: (Dict, Dict, str) -> None
def _list_configuration(self, config: Dict, raw: Dict, k: str = "") -> None:
orig_k = k
for key, value in sorted(config.items()):
if k + key in self.LIST_PROHIBITED_SETTINGS:
......@@ -319,8 +323,12 @@ To remove a repository (repo is a short alias for repositories):
self.line(message)
def _get_setting(
self, contents, setting=None, k=None, default=None
): # type: (Dict, Optional[str], Optional[str], Optional[Any]) -> List[Tuple[str, str]]
self,
contents: Dict,
setting: Optional[str] = None,
k: Optional[str] = None,
default: Optional[Any] = None,
) -> List[Tuple[str, str]]:
orig_k = k
if setting and setting.split(".")[0] not in contents:
......
......@@ -8,7 +8,7 @@ class DebugInfoCommand(Command):
name = "debug info"
description = "Shows debug information."
def handle(self): # type: () -> int
def handle(self) -> int:
poetry_python_version = ".".join(str(s) for s in sys.version_info[:3])
self.line("")
......
from typing import TYPE_CHECKING
from typing import Optional
from cleo.helpers import argument
......@@ -7,6 +8,10 @@ from cleo.io.outputs.output import Verbosity
from ..init import InitCommand
if TYPE_CHECKING:
from poetry.console.commands.show import ShowCommand
class DebugResolveCommand(InitCommand):
name = "debug resolve"
......@@ -30,7 +35,7 @@ class DebugResolveCommand(InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from cleo.io.null_io import NullIO
from poetry.core.packages.project_package import ProjectPackage
......@@ -88,7 +93,7 @@ class DebugResolveCommand(InitCommand):
self.line("")
if self.option("tree"):
show_command = self.application.find("show")
show_command: ShowCommand = self.application.find("show")
show_command.init_styles(self.io)
packages = [op.package for op in ops]
......
......@@ -7,7 +7,7 @@ from ..command import Command
if TYPE_CHECKING:
from poetry.utils.env import Env # noqa
from poetry.utils.env import Env
class EnvInfoCommand(Command):
......@@ -17,7 +17,7 @@ class EnvInfoCommand(Command):
options = [option("path", "p", "Only display the environment's path.")]
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from poetry.utils.env import EnvManager
env = EnvManager(self.poetry).get()
......@@ -32,7 +32,7 @@ class EnvInfoCommand(Command):
self._display_complete_info(env)
def _display_complete_info(self, env): # type: ("Env") -> None
def _display_complete_info(self, env: "Env") -> None:
env_python_version = ".".join(str(s) for s in env.version_info[:3])
self.line("")
self.line("<b>Virtualenv</b>")
......
......@@ -10,7 +10,7 @@ class EnvListCommand(Command):
options = [option("full-path", None, "Output the full paths of the virtualenvs.")]
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry)
......
......@@ -12,7 +12,7 @@ class EnvRemoveCommand(Command):
argument("python", "The python executable to remove the virtualenv for.")
]
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry)
......
......@@ -10,7 +10,7 @@ class EnvUseCommand(Command):
arguments = [argument("python", "The python executable to use.")]
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry)
......
......@@ -4,18 +4,18 @@ from .command import Command
if TYPE_CHECKING:
from poetry.utils.env import VirtualEnv # noqa
from poetry.utils.env import VirtualEnv
class EnvCommand(Command):
def __init__(self): # type: () -> None
def __init__(self) -> None:
self._env = None
super(EnvCommand, self).__init__()
@property
def env(self): # type: () -> "VirtualEnv"
def env(self) -> "VirtualEnv":
return self._env
def set_env(self, env): # type: ("VirtualEnv") -> None
def set_env(self, env: "VirtualEnv") -> None:
self._env = env
......@@ -31,7 +31,7 @@ class ExportCommand(Command):
option("with-credentials", None, "Include credentials for extra indices."),
]
def handle(self): # type: () -> None
def handle(self) -> None:
fmt = self.option("format")
if fmt not in Exporter.ACCEPTED_FORMATS:
......
......@@ -7,6 +7,7 @@ import sys
import urllib.parse
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from typing import Optional
......@@ -23,6 +24,10 @@ from .command import Command
from .env_command import EnvCommand
if TYPE_CHECKING:
from poetry.repositories import Pool
class InitCommand(Command):
name = "init"
description = (
......@@ -57,12 +62,12 @@ class InitCommand(Command):
The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the current directory.
"""
def __init__(self): # type: () -> None
def __init__(self) -> None:
super(InitCommand, self).__init__()
self._pool = None
def handle(self): # type: () -> int
def handle(self) -> int:
from pathlib import Path
from poetry.core.vcs.git import GitConfig
......@@ -227,8 +232,11 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
f.write(content)
def _determine_requirements(
self, requires, allow_prereleases=False, source=None
): # type: (List[str], bool, Optional[str]) -> List[Dict[str, Union[str, List[str]]]]
self,
requires: List[str],
allow_prereleases: bool = False,
source: Optional[str] = None,
) -> List[Dict[str, Union[str, List[str]]]]:
if not requires:
requires = []
......@@ -354,8 +362,12 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return result
def _find_best_version_for_package(
self, name, required_version=None, allow_prereleases=False, source=None
): # type: (str, Optional[str], bool, Optional[str]) -> Tuple[str, str]
self,
name: str,
required_version: Optional[str] = None,
allow_prereleases: bool = False,
source: Optional[str] = None,
) -> Tuple[str, str]:
from poetry.version.version_selector import VersionSelector
selector = VersionSelector(self._get_pool())
......@@ -371,9 +383,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return package.pretty_name, selector.find_recommended_require_version(package)
def _parse_requirements(
self, requirements
): # type: (List[str]) -> List[Dict[str, str]]
def _parse_requirements(self, requirements: List[str]) -> List[Dict[str, str]]:
from poetry.puzzle.provider import Provider
result = []
......@@ -490,8 +500,8 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return result
def _format_requirements(
self, requirements
): # type: (List[Dict[str, str]]) -> Dict[str, Union[str, Dict[str, str]]]
self, requirements: List[Dict[str, str]]
) -> Dict[str, Union[str, Dict[str, str]]]:
requires = {}
for requirement in requirements:
name = requirement.pop("name")
......@@ -506,7 +516,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return requires
def _validate_author(self, author, default): # type: (str, str) -> Optional[str]
def _validate_author(self, author: str, default: str) -> Optional[str]:
from poetry.core.packages.package import AUTHOR_REGEX
author = author or default
......@@ -523,7 +533,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return author
def _validate_license(self, license): # type: (str) -> str
def _validate_license(self, license: str) -> str:
from poetry.core.spdx import license_by_id
if license:
......@@ -531,7 +541,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return license
def _get_pool(self): # type: () -> "Pool"
def _get_pool(self) -> "Pool":
from poetry.repositories import Pool
from poetry.repositories.pypi_repository import PyPiRepository
......
......@@ -50,7 +50,7 @@ dependencies and not including the current project, run the command with the
_loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> int
def handle(self) -> int:
from poetry.core.masonry.utils.module import ModuleOrPackageNotFound
from poetry.masonry.builders import EditableBuilder
......
......@@ -9,20 +9,20 @@ if TYPE_CHECKING:
class InstallerCommand(EnvCommand):
def __init__(self): # type: () -> None
self._installer = None # type: Optional[Installer]
def __init__(self) -> None:
self._installer: Optional["Installer"] = None
super(InstallerCommand, self).__init__()
def reset_poetry(self): # type: () -> None
def reset_poetry(self) -> None:
super(InstallerCommand, self).reset_poetry()
self._installer.set_package(self.poetry.package)
self._installer.set_locker(self.poetry.locker)
@property
def installer(self): # type: () -> Installer
def installer(self) -> "Installer":
return self._installer
def set_installer(self, installer): # type: (Installer) -> None
def set_installer(self, installer: "Installer") -> None:
self._installer = installer
......@@ -24,7 +24,7 @@ file.
loggers = ["poetry.repositories.pypi_repository"]
def handle(self): # type: () -> int
def handle(self) -> int:
self._installer.use_executor(
self.poetry.config.get("experimental.new-installer", False)
)
......
......@@ -19,7 +19,7 @@ class NewCommand(Command):
option("src", None, "Use the src layout for the project."),
]
def handle(self): # type: () -> None
def handle(self) -> None:
from pathlib import Path
from poetry.core.semver import parse_constraint
......
......@@ -41,7 +41,7 @@ the config command.
loggers = ["poetry.masonry.publishing.publisher"]
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from poetry.publishing.publisher import Publisher
publisher = Publisher(self.poetry, self.io)
......
......@@ -27,7 +27,7 @@ list of installed packages
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> int
def handle(self) -> int:
packages = self.argument("packages")
is_dev = self.option("dev")
......
from typing import TYPE_CHECKING
from typing import Any
from typing import Union
......@@ -6,6 +7,10 @@ from cleo.helpers import argument
from .env_command import EnvCommand
if TYPE_CHECKING:
from poetry.core.masonry.utils.module import Module
class RunCommand(EnvCommand):
name = "run"
......@@ -15,7 +20,7 @@ class RunCommand(EnvCommand):
argument("args", "The command and arguments/options to run.", multiple=True)
]
def handle(self): # type: () -> Any
def handle(self) -> Any:
args = self.argument("args")
script = args[0]
scripts = self.poetry.local_config.get("scripts")
......@@ -26,7 +31,7 @@ class RunCommand(EnvCommand):
return self.env.execute(*args)
@property
def _module(self):
def _module(self) -> "Module":
from poetry.core.masonry.utils.module import Module
poetry = self.poetry
......@@ -36,7 +41,7 @@ class RunCommand(EnvCommand):
return module
def run_script(self, script, args): # type: (Union[str, dict], str) -> Any
def run_script(self, script: Union[str, dict], args: str) -> Any:
if isinstance(script, dict):
script = script["callable"]
......
......@@ -10,7 +10,7 @@ class SearchCommand(Command):
arguments = [argument("tokens", "The tokens to search for.", multiple=True)]
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.repositories.pypi_repository import PyPiRepository
results = PyPiRepository().search(self.argument("tokens"))
......
......@@ -11,6 +11,7 @@ import tarfile
from functools import cmp_to_key
from gzip import GzipFile
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
......@@ -24,9 +25,8 @@ from ..command import Command
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
from poetry.core.semver import Version
from poetry.utils._compat import Path
try:
......@@ -70,24 +70,24 @@ class SelfUpdateCommand(Command):
BASE_URL = REPOSITORY_URL + "/releases/download"
@property
def home(self): # type: () -> Path
def home(self) -> Path:
from pathlib import Path
return Path(os.environ.get("POETRY_HOME", "~/.poetry")).expanduser()
@property
def bin(self): # type: () -> Path
def bin(self) -> Path:
return self.home / "bin"
@property
def lib(self): # type: () -> Path
def lib(self) -> Path:
return self.home / "lib"
@property
def lib_backup(self): # type: () -> Path
def lib_backup(self) -> Path:
return self.home / "lib-backup"
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.__version__ import __version__
from poetry.core.semver import Version
from poetry.repositories.pypi_repository import PyPiRepository
......@@ -138,7 +138,7 @@ class SelfUpdateCommand(Command):
self.update(release)
def update(self, release): # type: ("Package") -> None
def update(self, release: "Package") -> None:
version = release.version
self.line("Updating to <info>{}</info>".format(version))
......@@ -174,7 +174,7 @@ class SelfUpdateCommand(Command):
)
)
def _update(self, version): # type: ("Version") -> None
def _update(self, version: "Version") -> None:
from poetry.utils.helpers import temporary_directory
release_name = self._get_release_name(version)
......@@ -244,10 +244,10 @@ class SelfUpdateCommand(Command):
finally:
gz.close()
def process(self, *args): # type: (*Any) -> str
def process(self, *args: Any) -> str:
return subprocess.check_output(list(args), stderr=subprocess.STDOUT)
def _check_recommended_installation(self): # type: () -> None
def _check_recommended_installation(self) -> None:
from pathlib import Path
current = Path(__file__)
......@@ -259,14 +259,14 @@ class SelfUpdateCommand(Command):
"so it cannot be updated automatically."
)
def _get_release_name(self, version): # type: ("Version") -> str
def _get_release_name(self, version: "Version") -> str:
platform = sys.platform
if platform == "linux2":
platform = "linux"
return "poetry-{}-{}".format(version, platform)
def make_bin(self): # type: () -> None
def make_bin(self) -> None:
from poetry.utils._compat import WINDOWS
self.bin.mkdir(0o755, parents=True, exist_ok=True)
......@@ -295,7 +295,7 @@ class SelfUpdateCommand(Command):
st = os.stat(str(self.bin.joinpath("poetry")))
os.chmod(str(self.bin.joinpath("poetry")), st.st_mode | stat.S_IEXEC)
def _which_python(self): # type: () -> str
def _which_python(self) -> str:
"""
Decides which python executable we'll embed in the launcher script.
"""
......
......@@ -16,7 +16,7 @@ class ShellCommand(EnvCommand):
If one doesn't exist yet, it will be created.
"""
def handle(self): # type: () -> None
def handle(self) -> None:
from poetry.utils.shell import Shell
# Check if it's already activated or doesn't exist and won't be created
......
......@@ -13,8 +13,8 @@ from .env_command import EnvCommand
if TYPE_CHECKING:
from cleo.io.io import IO # noqa
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository
......@@ -46,7 +46,7 @@ lists all packages available."""
colors = ["cyan", "yellow", "green", "magenta", "blue"]
def handle(self): # type: () -> Optional[int]
def handle(self) -> Optional[int]:
from cleo.io.null_io import NullIO
from cleo.terminal import Terminal
......@@ -271,8 +271,8 @@ lists all packages available."""
self.line(line)
def display_package_tree(
self, io, package, installed_repo
): # type: ("IO", "Package", "Repository") -> None
self, io: "IO", package: "Package", installed_repo: "Repository"
) -> None:
io.write("<c1>{}</c1>".format(package.pretty_name))
description = ""
if package.description:
......@@ -309,13 +309,13 @@ lists all packages available."""
def _display_tree(
self,
io, # type: "IO"
dependency, # type: "Dependency"
installed_repo, # type: "Repository"
packages_in_tree, # type: List[str]
previous_tree_bar="├", # type: str
level=1, # type: int
): # type: (...) -> None
io: "IO",
dependency: "Dependency",
installed_repo: "Repository",
packages_in_tree: List[str],
previous_tree_bar: str = "├",
level: int = 1,
) -> None:
previous_tree_bar = previous_tree_bar.replace("├", "│")
dependencies = []
......@@ -360,7 +360,7 @@ lists all packages available."""
io, dependency, installed_repo, current_tree, tree_bar, level + 1
)
def _write_tree_line(self, io, line): # type: ("IO", str) -> None
def _write_tree_line(self, io: "IO", line: str) -> None:
if not io.output.supports_utf8():
line = line.replace("└", "`-")
line = line.replace("├", "|-")
......@@ -369,7 +369,7 @@ lists all packages available."""
io.write_line(line)
def init_styles(self, io): # type: ("IO") -> None
def init_styles(self, io: "IO") -> None:
from cleo.formatters.style import Style
for color in self.colors:
......@@ -378,8 +378,8 @@ lists all packages available."""
io.error_output.formatter.set_style(color, style)
def find_latest_package(
self, package, include_dev
): # type: ("Package", bool) -> Union["Package", bool]
self, package: "Package", include_dev: bool
) -> Union["Package", bool]:
from cleo.io.null_io import NullIO
from poetry.puzzle.provider import Provider
......@@ -407,7 +407,7 @@ lists all packages available."""
return selector.find_best_candidate(name, ">={}".format(package.pretty_version))
def get_update_status(self, latest, package): # type: ("Package", "Package") -> str
def get_update_status(self, latest: "Package", package: "Package") -> str:
from poetry.core.semver import parse_constraint
if latest.full_pretty_version == package.full_pretty_version:
......@@ -423,8 +423,8 @@ lists all packages available."""
return "update-possible"
def get_installed_status(
self, locked, installed_repo
): # type: ("Package", "InstalledRepository") -> str
self, locked: "Package", installed_repo: "InstalledRepository"
) -> str:
for package in installed_repo.packages:
if locked.name == package.name:
return "installed"
......
......@@ -27,7 +27,7 @@ class UpdateCommand(InstallerCommand):
loggers = ["poetry.repositories.pypi_repository"]
def handle(self): # type: () -> int
def handle(self) -> int:
packages = self.argument("packages")
self._installer.use_executor(
......
from typing import TYPE_CHECKING
from cleo.helpers import argument
from cleo.helpers import option
from .command import Command
if TYPE_CHECKING:
from poetry.core.semver import Version
class VersionCommand(Command):
name = "version"
......@@ -40,7 +46,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease.
"prerelease",
}
def handle(self): # type: () -> None
def handle(self) -> None:
version = self.argument("version")
if version:
......@@ -72,7 +78,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease.
)
)
def increment_version(self, version, rule): # type: (str, str) -> "Version"
def increment_version(self, version: str, rule: str) -> "Version":
from poetry.core.semver import Version
try:
......
......@@ -4,7 +4,7 @@ from .formatter import Formatter
class BuilderLogFormatter(Formatter):
def format(self, msg): # type: (str) -> str
def format(self, msg: str) -> str:
if msg.startswith("Building "):
msg = re.sub("Building (.+)", " - Building <info>\\1</info>", msg)
elif msg.startswith("Built "):
......
......@@ -2,5 +2,5 @@ import logging
class Formatter(object):
def format(self, record): # type: (logging.LogRecord) -> str
def format(self, record: logging.LogRecord) -> str:
raise NotImplementedError()
......@@ -6,7 +6,7 @@ from .formatters import FORMATTERS
if TYPE_CHECKING:
from logging import LogRecord # noqa
from logging import LogRecord
class IOFormatter(logging.Formatter):
......@@ -18,7 +18,7 @@ class IOFormatter(logging.Formatter):
"info": "fg=blue",
}
def format(self, record): # type: ("LogRecord") -> str
def format(self, record: "LogRecord") -> str:
if not record.exc_info:
level = record.levelname.lower()
msg = record.msg
......
......@@ -4,18 +4,18 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from logging import LogRecord # noqa
from logging import LogRecord
from cleo.io.io import IO # noqa
class IOHandler(logging.Handler):
def __init__(self, io): # type: ("IO") -> None
def __init__(self, io: "IO") -> None:
self._io = io
super(IOHandler, self).__init__()
def emit(self, record): # type: ("LogRecord") -> None
def emit(self, record: "LogRecord") -> None:
try:
msg = self.format(record)
level = record.levelname.lower()
......
......@@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import unicode_literals
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict
from typing import Optional
......@@ -19,14 +20,18 @@ from .poetry import Poetry
from .repositories.pypi_repository import PyPiRepository
if TYPE_CHECKING:
from .repositories.legacy_repository import LegacyRepository
class Factory(BaseFactory):
"""
Factory class to create various elements needed by Poetry.
"""
def create_poetry(
self, cwd=None, io=None
): # type: (Optional[Path], Optional[IO]) -> Poetry
self, cwd: Optional[Path] = None, io: Optional[IO] = None
) -> Poetry:
if io is None:
io = NullIO()
......@@ -100,7 +105,7 @@ class Factory(BaseFactory):
return poetry
@classmethod
def create_config(cls, io=None): # type: (Optional[IO]) -> Config
def create_config(cls, io: Optional[IO] = None) -> Config:
if io is None:
io = NullIO()
......@@ -136,8 +141,8 @@ class Factory(BaseFactory):
return config
def create_legacy_repository(
self, source, auth_config
): # type: (Dict[str, str], Config) -> "LegacyRepository"
self, source: Dict[str, str], auth_config: Config
) -> "LegacyRepository":
from .repositories.legacy_repository import LegacyRepository
from .utils.helpers import get_cert
from .utils.helpers import get_client_cert
......
......@@ -43,8 +43,8 @@ PEP517_META_BUILD_DEPS = ["pep517===0.8.2", "toml==0.10.1"]
class PackageInfoError(ValueError):
def __init__(
self, path, *reasons
): # type: (Union[Path, str], *Union[BaseException, str]) -> None
self, path: Union[Path, str], *reasons: Union[BaseException, str]
) -> None:
reasons = (
"Unable to determine package info for path: {}".format(str(path)),
) + reasons
......@@ -56,14 +56,14 @@ class PackageInfoError(ValueError):
class PackageInfo:
def __init__(
self,
name=None, # type: Optional[str]
version=None, # type: Optional[str]
summary=None, # type: Optional[str]
platform=None, # type: Optional[str]
requires_dist=None, # type: Optional[List[str]]
requires_python=None, # type: Optional[str]
files=None, # type: Optional[List[str]]
cache_version=None, # type: Optional[str]
name: Optional[str] = None,
version: Optional[str] = None,
summary: Optional[str] = None,
platform: Optional[str] = None,
requires_dist: Optional[List[str]] = None,
requires_python: Optional[str] = None,
files: Optional[List[str]] = None,
cache_version: Optional[str] = None,
):
self.name = name
self.version = version
......@@ -78,10 +78,10 @@ class PackageInfo:
self._source_reference = None
@property
def cache_version(self): # type: () -> Optional[str]
def cache_version(self) -> Optional[str]:
return self._cache_version
def update(self, other): # type: (PackageInfo) -> PackageInfo
def update(self, other: "PackageInfo") -> "PackageInfo":
self.name = other.name or self.name
self.version = other.version or self.version
self.summary = other.summary or self.summary
......@@ -92,7 +92,7 @@ class PackageInfo:
self._cache_version = other.cache_version or self._cache_version
return self
def asdict(self): # type: () -> Dict[str, Optional[Union[str, List[str]]]]
def asdict(self) -> Dict[str, Optional[Union[str, List[str]]]]:
"""
Helper method to convert package info into a dictionary used for caching.
"""
......@@ -108,9 +108,7 @@ class PackageInfo:
}
@classmethod
def load(
cls, data
): # type: (Dict[str, Optional[Union[str, List[str]]]]) -> PackageInfo
def load(cls, data: Dict[str, Optional[Union[str, List[str]]]]) -> "PackageInfo":
"""
Helper method to load data from a dictionary produced by `PackageInfo.asdict()`.
......@@ -120,13 +118,16 @@ class PackageInfo:
return cls(cache_version=cache_version, **data)
@classmethod
def _log(cls, msg, level="info"): # type: (str, str) -> None
def _log(cls, msg: str, level: str = "info") -> None:
"""Internal helper method to log information."""
getattr(logger, level)("<debug>{}:</debug> {}".format(cls.__name__, msg))
def to_package(
self, name=None, extras=None, root_dir=None
): # type: (Optional[str], Optional[List[str]], Optional[Path]) -> Package
self,
name: Optional[str] = None,
extras: Optional[List[str]] = None,
root_dir: Optional[Path] = None,
) -> Package:
"""
Create a new `poetry.core.packages.package.Package` instance using metadata from this instance.
......@@ -202,8 +203,8 @@ class PackageInfo:
@classmethod
def _from_distribution(
cls, dist
): # type: (Union[pkginfo.BDist, pkginfo.SDist, pkginfo.Wheel]) -> PackageInfo
cls, dist: Union[pkginfo.BDist, pkginfo.SDist, pkginfo.Wheel]
) -> "PackageInfo":
"""
Helper method to parse package information from a `pkginfo.Distribution` instance.
......@@ -234,7 +235,7 @@ class PackageInfo:
return info
@classmethod
def _from_sdist_file(cls, path): # type: (Path) -> PackageInfo
def _from_sdist_file(cls, path: Path) -> "PackageInfo":
"""
Helper method to parse package information from an sdist file. We attempt to first inspect the
file using `pkginfo.SDist`. If this does not provide us with package requirements, we extract the
......@@ -295,11 +296,11 @@ class PackageInfo:
return info.update(new_info)
@staticmethod
def has_setup_files(path): # type: (Path) -> bool
def has_setup_files(path: Path) -> bool:
return any((path / f).exists() for f in SetupReader.FILES)
@classmethod
def from_setup_files(cls, path): # type: (Path) -> PackageInfo
def from_setup_files(cls, path: Path) -> "PackageInfo":
"""
Mechanism to parse package information from a `setup.[py|cfg]` file. This uses the implementation
at `poetry.utils.setup_reader.SetupReader` in order to parse the file. This is not reliable for
......@@ -356,7 +357,7 @@ class PackageInfo:
return info
@staticmethod
def _find_dist_info(path): # type: (Path) -> Iterator[Path]
def _find_dist_info(path: Path) -> Iterator[Path]:
"""
Discover all `*.*-info` directories in a given path.
......@@ -372,7 +373,7 @@ class PackageInfo:
yield Path(d)
@classmethod
def from_metadata(cls, path): # type: (Path) -> Optional[PackageInfo]
def from_metadata(cls, path: Path) -> Optional["PackageInfo"]:
"""
Helper method to parse package information from an unpacked metadata directory.
......@@ -406,7 +407,7 @@ class PackageInfo:
return info
@classmethod
def from_package(cls, package): # type: (Package) -> PackageInfo
def from_package(cls, package: Package) -> "PackageInfo":
"""
Helper method to inspect a `Package` object, in order to generate package info.
......@@ -429,14 +430,14 @@ class PackageInfo:
)
@staticmethod
def _get_poetry_package(path): # type: (Path) -> Optional[ProjectPackage]
def _get_poetry_package(path: Path) -> Optional[ProjectPackage]:
# Note: we ignore any setup.py file at this step
# TODO: add support for handling non-poetry PEP-517 builds
if PyProjectTOML(path.joinpath("pyproject.toml")).is_poetry_project():
return Factory().create_poetry(path).package
@classmethod
def _pep517_metadata(cls, path): # type: (Path) -> PackageInfo
def _pep517_metadata(cls, path: Path) -> "PackageInfo":
"""
Helper method to use PEP-517 library to build and read package metadata.
......@@ -511,9 +512,7 @@ class PackageInfo:
raise PackageInfoError(path, "Exhausted all core metadata sources.")
@classmethod
def from_directory(
cls, path, disable_build=False
): # type: (Path, bool) -> PackageInfo
def from_directory(cls, path: Path, disable_build: bool = False) -> "PackageInfo":
"""
Generate package information from a package source directory. If `disable_build` is not `True` and
introspection of all available metadata fails, the package is attempted to be build in an isolated
......@@ -547,7 +546,7 @@ class PackageInfo:
return info
@classmethod
def from_sdist(cls, path): # type: (Path) -> PackageInfo
def from_sdist(cls, path: Path) -> "PackageInfo":
"""
Gather package information from an sdist file, packed or unpacked.
......@@ -561,7 +560,7 @@ class PackageInfo:
return cls.from_directory(path=path)
@classmethod
def from_wheel(cls, path): # type: (Path) -> PackageInfo
def from_wheel(cls, path: Path) -> "PackageInfo":
"""
Gather package information from a wheel.
......@@ -573,7 +572,7 @@ class PackageInfo:
return PackageInfo()
@classmethod
def from_bdist(cls, path): # type: (Path) -> PackageInfo
def from_bdist(cls, path: Path) -> "PackageInfo":
"""
Gather package information from a bdist (wheel etc.).
......@@ -591,7 +590,7 @@ class PackageInfo:
raise PackageInfoError(path, e)
@classmethod
def from_path(cls, path): # type: (Path) -> PackageInfo
def from_path(cls, path: Path) -> "PackageInfo":
"""
Gather package information from a given path (bdist, sdist, directory).
......
......@@ -3,6 +3,9 @@ import time
import urllib.parse
from typing import TYPE_CHECKING
from typing import Any
from typing import Optional
from typing import Tuple
import requests
import requests.auth
......@@ -13,10 +16,6 @@ from poetry.utils.password_manager import PasswordManager
if TYPE_CHECKING:
from typing import Any
from typing import Optional
from typing import Tuple
from cleo.io.io import IO
from poetry.config.config import Config
......@@ -26,14 +25,14 @@ logger = logging.getLogger()
class Authenticator(object):
def __init__(self, config, io=None): # type: (Config, Optional[IO]) -> None
def __init__(self, config: "Config", io: Optional["IO"] = None) -> None:
self._config = config
self._io = io
self._session = None
self._credentials = {}
self._password_manager = PasswordManager(self._config)
def _log(self, message, level="debug"): # type: (str, str) -> None
def _log(self, message: str, level: str = "debug") -> None:
if self._io is not None:
self._io.write_line(
"<{level:s}>{message:s}</{level:s}>".format(
......@@ -44,15 +43,13 @@ class Authenticator(object):
getattr(logger, level, logger.debug)(message)
@property
def session(self): # type: () -> requests.Session
def session(self) -> requests.Session:
if self._session is None:
self._session = requests.Session()
return self._session
def request(
self, method, url, **kwargs
): # type: (str, str, Any) -> requests.Response
def request(self, method: str, url: str, **kwargs: Any) -> requests.Response:
request = requests.Request(method, url)
username, password = self.get_credentials_for_url(url)
......@@ -104,9 +101,7 @@ class Authenticator(object):
# this should never really be hit under any sane circumstance
raise PoetryException("Failed HTTP {} request", method.upper())
def get_credentials_for_url(
self, url
): # type: (str) -> Tuple[Optional[str], Optional[str]]
def get_credentials_for_url(self, url: str) -> Tuple[Optional[str], Optional[str]]:
parsed_url = urllib.parse.urlsplit(url)
netloc = parsed_url.netloc
......@@ -141,8 +136,8 @@ class Authenticator(object):
return credentials[0], credentials[1]
def _get_credentials_for_netloc_from_config(
self, netloc
): # type: (str) -> Tuple[Optional[str], Optional[str]]
self, netloc: str
) -> Tuple[Optional[str], Optional[str]]:
credentials = (None, None)
for repository_name in self._config.get("repositories", []):
......
......@@ -2,15 +2,15 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class BaseInstaller:
def install(self, package): # type: ("Package") -> None
def install(self, package: "Package") -> None:
raise NotImplementedError
def update(self, source, target): # type: ("Package", "Package") -> None
def update(self, source: "Package", target: "Package") -> None:
raise NotImplementedError
def remove(self, package): # type: ("Package") -> None
def remove(self, package: "Package") -> None:
raise NotImplementedError
......@@ -3,6 +3,8 @@ import json
from pathlib import Path
from typing import TYPE_CHECKING
from typing import List
from typing import Optional
from poetry.core.packages.utils.link import Link
......@@ -11,37 +13,35 @@ from .chooser import Wheel
if TYPE_CHECKING:
from typing import List
from typing import Optional
from poetry.config.config import Config
from poetry.utils.env import Env
class Chef:
def __init__(self, config, env): # type: (Config, Env) -> None
def __init__(self, config: "Config", env: "Env") -> None:
self._config = config
self._env = env
self._cache_dir = (
Path(config.get("cache-dir")).expanduser().joinpath("artifacts")
)
def prepare(self, archive): # type: (Path) -> Path
def prepare(self, archive: Path) -> Path:
return archive
def prepare_sdist(self, archive): # type: (Path) -> Path
def prepare_sdist(self, archive: Path) -> Path:
return archive
def prepare_wheel(self, archive): # type: (Path) -> Path
def prepare_wheel(self, archive: Path) -> Path:
return archive
def should_prepare(self, archive): # type: (Path) -> bool
def should_prepare(self, archive: Path) -> bool:
return not self.is_wheel(archive)
def is_wheel(self, archive): # type: (Path) -> bool
def is_wheel(self, archive: Path) -> bool:
return archive.suffix == ".whl"
def get_cached_archive_for_link(self, link): # type: (Link) -> Optional[Link]
def get_cached_archive_for_link(self, link: Link) -> Optional[Link]:
# If the archive is already a wheel, there is no need to cache it.
if link.is_wheel:
pass
......@@ -74,7 +74,7 @@ class Chef:
return min(candidates)[1]
def get_cached_archives_for_link(self, link): # type: (Link) -> List[Link]
def get_cached_archives_for_link(self, link: Link) -> List[Link]:
cache_dir = self.get_cache_directory_for_link(link)
archive_types = ["whl", "tar.gz", "tar.bz2", "bz2", "zip"]
......@@ -85,7 +85,7 @@ class Chef:
return links
def get_cache_directory_for_link(self, link): # type: (Link) -> Path
def get_cache_directory_for_link(self, link: Link) -> Path:
key_parts = {"url": link.url_without_fragment}
if link.hash_name is not None and link.hash is not None:
......
......@@ -18,7 +18,7 @@ class InvalidWheelName(Exception):
class Wheel(object):
def __init__(self, filename): # type: (str) -> None
def __init__(self, filename: str) -> None:
wheel_info = wheel_file_re.match(filename)
if not wheel_info:
raise InvalidWheelName("{} is not a valid wheel filename.".format(filename))
......@@ -35,12 +35,12 @@ class Wheel(object):
Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats
}
def get_minimum_supported_index(self, tags): # type: (List[Tag]) -> Optional[int]
def get_minimum_supported_index(self, tags: List[Tag]) -> Optional[int]:
indexes = [tags.index(t) for t in self.tags if t in tags]
return min(indexes) if indexes else None
def is_supported_by_environment(self, env): # type: (Env) -> bool
def is_supported_by_environment(self, env: Env) -> bool:
return bool(set(env.supported_tags).intersection(self.tags))
......@@ -49,11 +49,11 @@ class Chooser:
A Chooser chooses an appropriate release archive for packages.
"""
def __init__(self, pool, env): # type: (Pool, Env) -> None
def __init__(self, pool: Pool, env: Env) -> None:
self._pool = pool
self._env = env
def choose_for(self, package): # type: (Package) -> Link
def choose_for(self, package: Package) -> Link:
"""
Return the url of the selected archive for a given package.
"""
......@@ -83,7 +83,7 @@ class Chooser:
return chosen
def _get_links(self, package): # type: (Package) -> List[Link]
def _get_links(self, package: Package) -> List[Link]:
if not package.source_type:
if not self._pool.has_repository("pypi"):
repository = self._pool.repositories[0]
......@@ -112,7 +112,7 @@ class Chooser:
return selected_links
def _sort_key(self, package, link): # type: (Package, Link) -> Tuple
def _sort_key(self, package: Package, link: Link) -> Tuple:
"""
Function to pass as the `key` argument to a call to sorted() to sort
InstallationCandidates by preference.
......@@ -170,9 +170,7 @@ class Chooser:
pri,
)
def _is_link_hash_allowed_for_package(
self, link, package
): # type: (Link, Package) -> bool
def _is_link_hash_allowed_for_package(self, link: Link, package: Package) -> bool:
if not link.hash:
return True
......
......@@ -35,17 +35,22 @@ from .operations.update import Update
if TYPE_CHECKING:
from cleo.io.io import IO # noqa
from poetry.config.config import Config # noqa
from poetry.repositories import Pool # noqa
from poetry.utils.env import Env # noqa
from poetry.config.config import Config
from poetry.repositories import Pool
from poetry.utils.env import Env
from .operations import OperationTypes # noqa
from .operations import OperationTypes
class Executor(object):
def __init__(
self, env, pool, config, io, parallel=None
): # type: ("Env", "Pool", "Config", "IO", bool) -> None
self,
env: "Env",
pool: "Pool",
config: "Config",
io: "IO",
parallel: bool = None,
) -> None:
self._env = env
self._io = io
self._dry_run = False
......@@ -80,36 +85,36 @@ class Executor(object):
self._shutdown = False
@property
def installations_count(self): # type: () -> int
def installations_count(self) -> int:
return self._executed["install"]
@property
def updates_count(self): # type: () -> int
def updates_count(self) -> int:
return self._executed["update"]
@property
def removals_count(self): # type: () -> int
def removals_count(self) -> int:
return self._executed["uninstall"]
def supports_fancy_output(self): # type: () -> bool
def supports_fancy_output(self) -> bool:
return self._io.output.is_decorated() and not self._dry_run
def disable(self): # type: () -> "Executor"
def disable(self) -> "Executor":
self._enabled = False
return self
def dry_run(self, dry_run=True): # type: (bool) -> Executor
def dry_run(self, dry_run: bool = True) -> "Executor":
self._dry_run = dry_run
return self
def verbose(self, verbose=True): # type: (bool) -> Executor
def verbose(self, verbose: bool = True) -> "Executor":
self._verbose = verbose
return self
def execute(self, operations): # type: (List["OperationTypes"]) -> int
def execute(self, operations: List["OperationTypes"]) -> int:
self._total_operations = len(operations)
for job_type in self._executed:
self._executed[job_type] = 0
......@@ -162,7 +167,7 @@ class Executor(object):
return 1 if self._shutdown else 0
def _write(self, operation, line): # type: ("OperationTypes", str) -> None
def _write(self, operation: "OperationTypes", line: str) -> None:
if not self.supports_fancy_output() or not self._should_write_operation(
operation
):
......@@ -180,7 +185,7 @@ class Executor(object):
section.clear()
section.write(line)
def _execute_operation(self, operation): # type: ("OperationTypes") -> None
def _execute_operation(self, operation: "OperationTypes") -> None:
try:
if self.supports_fancy_output():
if id(operation) not in self._sections:
......@@ -259,7 +264,7 @@ class Executor(object):
with self._lock:
self._shutdown = True
def _do_execute_operation(self, operation): # type: ("OperationTypes") -> int
def _do_execute_operation(self, operation: "OperationTypes") -> int:
method = operation.job_type
operation_message = self.get_operation_message(operation)
......@@ -304,8 +309,8 @@ class Executor(object):
return result
def _increment_operations_count(
self, operation, executed
): # type: ("OperationTypes", bool) -> None
self, operation: "OperationTypes", executed: bool
) -> None:
with self._lock:
if executed:
self._executed_operations += 1
......@@ -313,7 +318,7 @@ class Executor(object):
else:
self._skipped[operation.job_type] += 1
def run_pip(self, *args, **kwargs): # type: (*Any, **Any) -> int
def run_pip(self, *args: Any, **kwargs: Any) -> int:
try:
self._env.run_pip(*args, **kwargs)
except EnvCommandError as e:
......@@ -329,8 +334,12 @@ class Executor(object):
return 0
def get_operation_message(
self, operation, done=False, error=False, warning=False
): # type: ("OperationTypes", bool, bool, bool) -> str
self,
operation: "OperationTypes",
done: bool = False,
error: bool = False,
warning: bool = False,
) -> str:
base_tag = "fg=default"
operation_color = "c2"
source_operation_color = "c2"
......@@ -384,7 +393,7 @@ class Executor(object):
return ""
def _display_summary(self, operations): # type: (List["OperationTypes"]) -> None
def _display_summary(self, operations: List["OperationTypes"]) -> None:
installs = 0
updates = 0
uninstalls = 0
......@@ -427,13 +436,13 @@ class Executor(object):
)
self._io.write_line("")
def _execute_install(self, operation): # type: (Union[Install, Update]) -> int
def _execute_install(self, operation: Union[Install, Update]) -> int:
return self._install(operation)
def _execute_update(self, operation): # type: (Union[Install, Update]) -> int
def _execute_update(self, operation: Union[Install, Update]) -> int:
return self._update(operation)
def _execute_uninstall(self, operation): # type: (Uninstall) -> int
def _execute_uninstall(self, operation: Uninstall) -> int:
message = (
" <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format(
message=self.get_operation_message(operation),
......@@ -443,7 +452,7 @@ class Executor(object):
return self._remove(operation)
def _install(self, operation): # type: (Union[Install, Update]) -> int
def _install(self, operation: Union[Install, Update]) -> int:
package = operation.package
if package.source_type == "directory":
return self._install_directory(operation)
......@@ -472,10 +481,10 @@ class Executor(object):
return self.run_pip(*args)
def _update(self, operation): # type: (Union[Install, Update]) -> int
def _update(self, operation: Union[Install, Update]) -> int:
return self._install(operation)
def _remove(self, operation): # type: (Uninstall) -> int
def _remove(self, operation: Uninstall) -> int:
package = operation.package
# If we have a VCS package, remove its source directory
......@@ -492,7 +501,7 @@ class Executor(object):
raise
def _prepare_file(self, operation): # type: (Union[Install, Update]) -> Path
def _prepare_file(self, operation: Union[Install, Update]) -> Path:
package = operation.package
message = (
......@@ -510,7 +519,7 @@ class Executor(object):
return archive
def _install_directory(self, operation): # type: (Union[Install, Update]) -> int
def _install_directory(self, operation: Union[Install, Update]) -> int:
from poetry.factory import Factory
package = operation.package
......@@ -576,7 +585,7 @@ class Executor(object):
return self.run_pip(*args)
def _install_git(self, operation): # type: (Union[Install, Update]) -> int
def _install_git(self, operation: Union[Install, Update]) -> int:
from poetry.core.vcs import Git
package = operation.package
......@@ -604,14 +613,12 @@ class Executor(object):
return self._install_directory(operation)
def _download(self, operation): # type: (Union[Install, Update]) -> Link
def _download(self, operation: Union[Install, Update]) -> Link:
link = self._chooser.choose_for(operation.package)
return self._download_link(operation, link)
def _download_link(
self, operation, link
): # type: (Union[Install, Update], Link) -> Link
def _download_link(self, operation: Union[Install, Update], link: Link) -> Link:
package = operation.package
archive = self._chef.get_cached_archive_for_link(link)
......@@ -643,9 +650,7 @@ class Executor(object):
return archive
def _download_archive(
self, operation, link
): # type: (Union[Install, Update], Link) -> Path
def _download_archive(self, operation: Union[Install, Update], link: Link) -> Path:
response = self._authenticator.request(
"get", link.url, stream=True, io=self._sections.get(id(operation), self._io)
)
......@@ -694,7 +699,7 @@ class Executor(object):
return archive
def _should_write_operation(self, operation): # type: (Operation) -> bool
def _should_write_operation(self, operation: Operation) -> bool:
if not operation.skipped:
return True
......
......@@ -26,22 +26,22 @@ from .pip_installer import PipInstaller
if TYPE_CHECKING:
from poetry.utils.env import Env # noqa
from poetry.utils.env import Env
from .operations import OperationTypes # noqa
from .operations import OperationTypes
class Installer:
def __init__(
self,
io, # type: IO
env, # type: "Env"
package, # type: ProjectPackage
locker, # type: Locker
pool, # type: Pool
config, # type: Config
installed=None, # type: Union[InstalledRepository, None]
executor=None, # type: Optional[Executor]
io: IO,
env: "Env",
package: ProjectPackage,
locker: Locker,
pool: Pool,
config: Config,
installed: Union[InstalledRepository, None] = None,
executor: Optional[Executor] = None,
):
self._io = io
self._env = env
......@@ -76,24 +76,24 @@ class Installer:
self._installed_repository = installed
@property
def executor(self): # type: () -> Executor
def executor(self) -> Executor:
return self._executor
@property
def installer(self): # type: () -> BaseInstaller
def installer(self) -> BaseInstaller:
return self._installer
def set_package(self, package): # type: (ProjectPackage) -> Installer
def set_package(self, package: ProjectPackage) -> "Installer":
self._package = package
return self
def set_locker(self, locker): # type: (Locker) -> Installer
def set_locker(self, locker: Locker) -> "Installer":
self._locker = locker
return self
def run(self): # type: () -> int
def run(self) -> int:
# Check if refresh
if not self._update and self._lock and self._locker.is_locked():
return self._do_refresh()
......@@ -111,54 +111,54 @@ class Installer:
return self._do_install(local_repo)
def dry_run(self, dry_run=True): # type: (bool) -> Installer
def dry_run(self, dry_run: bool = True) -> "Installer":
self._dry_run = dry_run
self._executor.dry_run(dry_run)
return self
def is_dry_run(self): # type: () -> bool
def is_dry_run(self) -> bool:
return self._dry_run
def remove_untracked(self, remove_untracked=True): # type: (bool) -> Installer
def remove_untracked(self, remove_untracked: bool = True) -> "Installer":
self._remove_untracked = remove_untracked
return self
def is_remove_untracked(self): # type: () -> bool
def is_remove_untracked(self) -> bool:
return self._remove_untracked
def verbose(self, verbose=True): # type: (bool) -> Installer
def verbose(self, verbose: bool = True) -> "Installer":
self._verbose = verbose
self._executor.verbose(verbose)
return self
def is_verbose(self): # type: () -> bool
def is_verbose(self) -> bool:
return self._verbose
def dev_mode(self, dev_mode=True): # type: (bool) -> Installer
def dev_mode(self, dev_mode: bool = True) -> "Installer":
self._dev_mode = dev_mode
return self
def is_dev_mode(self): # type: () -> bool
def is_dev_mode(self) -> bool:
return self._dev_mode
def dev_only(self, dev_only=False): # type: (bool) -> Installer
def dev_only(self, dev_only: bool = False) -> "Installer":
self._dev_only = dev_only
return self
def is_dev_only(self): # type: () -> bool
def is_dev_only(self) -> bool:
return self._dev_only
def update(self, update=True): # type: (bool) -> Installer
def update(self, update: bool = True) -> "Installer":
self._update = update
return self
def lock(self, update=True): # type: (bool) -> Installer
def lock(self, update: bool = True) -> "Installer":
"""
Prepare the installer for locking only.
"""
......@@ -168,10 +168,10 @@ class Installer:
return self
def is_updating(self): # type: () -> bool
def is_updating(self) -> bool:
return self._update
def execute_operations(self, execute=True): # type: (bool) -> Installer
def execute_operations(self, execute: bool = True) -> "Installer":
self._execute_operations = execute
if not execute:
......@@ -179,22 +179,22 @@ class Installer:
return self
def whitelist(self, packages): # type: (Iterable[str]) -> Installer
def whitelist(self, packages: Iterable[str]) -> "Installer":
self._whitelist = [canonicalize_name(p) for p in packages]
return self
def extras(self, extras): # type: (list) -> Installer
def extras(self, extras: list) -> "Installer":
self._extras = extras
return self
def use_executor(self, use_executor=True): # type: (bool) -> Installer
def use_executor(self, use_executor: bool = True) -> "Installer":
self._use_executor = use_executor
return self
def _do_refresh(self): # type: () -> int
def _do_refresh(self) -> int:
from poetry.puzzle import Solver
# Checking extras
......@@ -208,7 +208,7 @@ class Installer:
self._pool,
locked_repository,
locked_repository,
self._io, # noqa
self._io,
)
ops = solver.solve(use_latest=[])
......@@ -220,7 +220,7 @@ class Installer:
return 0
def _do_install(self, local_repo): # type: (Repository) -> int
def _do_install(self, local_repo: Repository) -> int:
from poetry.puzzle import Solver
locked_repository = Repository()
......@@ -335,7 +335,7 @@ class Installer:
# Execute operations
return self._execute(ops)
def _write_lock_file(self, repo, force=True): # type: (Repository, bool) -> None
def _write_lock_file(self, repo: Repository, force: bool = True) -> None:
if force or (self._update and self._write_lock):
updated_lock = self._locker.set_lock_data(self._package, repo.packages)
......@@ -343,7 +343,7 @@ class Installer:
self._io.write_line("")
self._io.write_line("<info>Writing lock file</>")
def _execute(self, operations): # type: (List["OperationTypes"]) -> int
def _execute(self, operations: List["OperationTypes"]) -> int:
if self._use_executor:
return self._executor.execute(operations)
......@@ -391,7 +391,7 @@ class Installer:
return 0
def _execute_operation(self, operation): # type: (Operation) -> None
def _execute_operation(self, operation: Operation) -> None:
"""
Execute a given operation.
"""
......@@ -399,7 +399,7 @@ class Installer:
getattr(self, "_execute_{}".format(method))(operation)
def _execute_install(self, operation): # type: (Install) -> None
def _execute_install(self, operation: Install) -> None:
if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.write_line(
......@@ -424,7 +424,7 @@ class Installer:
self._installer.install(operation.package)
def _execute_update(self, operation): # type: (Update) -> None
def _execute_update(self, operation: Update) -> None:
source = operation.initial_package
target = operation.target_package
......@@ -454,7 +454,7 @@ class Installer:
self._installer.update(source, target)
def _execute_uninstall(self, operation): # type: (Uninstall) -> None
def _execute_uninstall(self, operation: Uninstall) -> None:
if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.write_line(
......@@ -480,8 +480,8 @@ class Installer:
self._installer.remove(operation.package)
def _populate_local_repo(
self, local_repo, ops
): # type: (Repository, List[Operation]) -> None
self, local_repo: Repository, ops: List[Operation]
) -> None:
for op in ops:
if isinstance(op, Uninstall):
continue
......@@ -494,8 +494,8 @@ class Installer:
local_repo.add_package(package)
def _get_operations_from_lock(
self, locked_repository
): # type: (Repository) -> List[Operation]
self, locked_repository: Repository
) -> List[Operation]:
installed_repo = self._installed_repository
ops = []
......@@ -526,9 +526,7 @@ class Installer:
return ops
def _filter_operations(
self, ops, repo
): # type: (List[Operation], Repository) -> None
def _filter_operations(self, ops: List[Operation], repo: Repository) -> None:
extra_packages = self._get_extra_packages(repo)
for op in ops:
if isinstance(op, Update):
......@@ -563,7 +561,7 @@ class Installer:
if package.category == "dev" and not self.is_dev_mode():
op.skip("Dev dependencies not requested")
def _get_extra_packages(self, repo): # type: (Repository) -> List[str]
def _get_extra_packages(self, repo: Repository) -> List[str]:
"""
Returns all package names required by extras.
......@@ -576,8 +574,8 @@ class Installer:
return list(get_extra_package_names(repo.packages, extras, self._extras))
def _get_installer(self): # type: () -> BaseInstaller
def _get_installer(self) -> BaseInstaller:
return PipInstaller(self._env, self._io, self._pool)
def _get_installed(self): # type: () -> InstalledRepository
def _get_installed(self) -> InstalledRepository:
return InstalledRepository.load(self._env)
......@@ -5,32 +5,32 @@ from .base_installer import BaseInstaller
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class NoopInstaller(BaseInstaller):
def __init__(self): # type: () -> None
def __init__(self) -> None:
self._installs = []
self._updates = []
self._removals = []
@property
def installs(self): # type: () -> List["Package"]
def installs(self) -> List["Package"]:
return self._installs
@property
def updates(self): # type: () -> List["Package"]
def updates(self) -> List["Package"]:
return self._updates
@property
def removals(self): # type: () -> List["Package"]
def removals(self) -> List["Package"]:
return self._removals
def install(self, package): # type: ("Package") -> None
def install(self, package: "Package") -> None:
self._installs.append(package)
def update(self, source, target): # type: ("Package", "Package") -> None
def update(self, source: "Package", target: "Package") -> None:
self._updates.append((source, target))
def remove(self, package): # type: ("Package") -> None
def remove(self, package: "Package") -> None:
self._removals.append(package)
......@@ -5,31 +5,31 @@ from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class Install(Operation):
def __init__(
self, package, reason=None, priority=0
): # type: ("Package", Optional[str], int) -> None
self, package: "Package", reason: Optional[str] = None, priority: int = 0
) -> None:
super(Install, self).__init__(reason, priority=priority)
self._package = package
@property
def package(self): # type: () -> "Package"
def package(self) -> "Package":
return self._package
@property
def job_type(self): # type: () -> str
def job_type(self) -> str:
return "install"
def __str__(self): # type: () -> str
def __str__(self) -> str:
return "Installing {} ({})".format(
self.package.pretty_name, self.format_version(self.package)
)
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return "<Install {} ({})>".format(
self.package.pretty_name, self.format_version(self.package)
)
......@@ -5,11 +5,11 @@ from typing import Optional
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class Operation(object):
def __init__(self, reason=None, priority=0): # type: (Optional[str], int) -> None
def __init__(self, reason: Optional[str] = None, priority: int = 0) -> None:
self._reason = reason
self._skipped = False
......@@ -17,39 +17,39 @@ class Operation(object):
self._priority = priority
@property
def job_type(self): # type: () -> str
def job_type(self) -> str:
raise NotImplementedError
@property
def reason(self): # type: () -> str
def reason(self) -> str:
return self._reason
@property
def skipped(self): # type: () -> bool
def skipped(self) -> bool:
return self._skipped
@property
def skip_reason(self): # type: () -> Optional[str]
def skip_reason(self) -> Optional[str]:
return self._skip_reason
@property
def priority(self): # type: () -> int
def priority(self) -> int:
return self._priority
@property
def package(self): # type: () -> "Package"
def package(self) -> "Package":
raise NotImplementedError()
def format_version(self, package): # type: ("Package") -> str
def format_version(self, package: "Package") -> str:
return package.full_pretty_version
def skip(self, reason): # type: (str) -> Operation
def skip(self, reason: str) -> "Operation":
self._skipped = True
self._skip_reason = reason
return self
def unskip(self): # type: () -> Operation
def unskip(self) -> "Operation":
self._skipped = False
self._skip_reason = None
......
......@@ -5,31 +5,34 @@ from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class Uninstall(Operation):
def __init__(
self, package, reason=None, priority=float("inf")
): # type: ("Package", Optional[str], int) -> None
self,
package: "Package",
reason: Optional[str] = None,
priority: int = float("inf"),
) -> None:
super(Uninstall, self).__init__(reason, priority=priority)
self._package = package
@property
def package(self): # type: () -> "Package"
def package(self) -> "Package":
return self._package
@property
def job_type(self): # type: () -> str
def job_type(self) -> str:
return "uninstall"
def __str__(self): # type: () -> str
def __str__(self) -> str:
return "Uninstalling {} ({})".format(
self.package.pretty_name, self.format_version(self._package)
)
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return "<Uninstall {} ({})>".format(
self.package.pretty_name, self.format_version(self.package)
)
......@@ -5,35 +5,39 @@ from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class Update(Operation):
def __init__(
self, initial, target, reason=None, priority=0
): # type: ("Package", "Package", Optional[str], int) -> None
self,
initial: "Package",
target: "Package",
reason: Optional[str] = None,
priority: int = 0,
) -> None:
self._initial_package = initial
self._target_package = target
super(Update, self).__init__(reason, priority=priority)
@property
def initial_package(self): # type: () -> "Package"
def initial_package(self) -> "Package":
return self._initial_package
@property
def target_package(self): # type: () -> "Package"
def target_package(self) -> "Package":
return self._target_package
@property
def package(self): # type: () -> "Package"
def package(self) -> "Package":
return self._target_package
@property
def job_type(self): # type: () -> str
def job_type(self) -> str:
return "update"
def __str__(self): # type: () -> str
def __str__(self) -> str:
return "Updating {} ({}) to {} ({})".format(
self.initial_package.pretty_name,
self.format_version(self.initial_package),
......@@ -41,7 +45,7 @@ class Update(Operation):
self.format_version(self.target_package),
)
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return "<Update {} ({}) to {} ({})>".format(
self.initial_package.pretty_name,
self.format_version(self.initial_package),
......
......@@ -19,16 +19,16 @@ from .base_installer import BaseInstaller
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import Package
class PipInstaller(BaseInstaller):
def __init__(self, env, io, pool): # type: (Env, IO, Pool) -> None
def __init__(self, env: Env, io: IO, pool: Pool) -> None:
self._env = env
self._io = io
self._pool = pool
def install(self, package, update=False): # type: ("Package", bool) -> None
def install(self, package: "Package", update: bool = False) -> None:
if package.source_type == "directory":
self.install_directory(package)
......@@ -48,7 +48,7 @@ class PipInstaller(BaseInstaller):
repository = self._pool.repository(package.source_reference)
parsed = urllib.parse.urlparse(package.source_url)
if parsed.scheme == "http":
self._io.error(
self._io.write_error(
" <warning>Installing from unsecure host: {}</warning>".format(
parsed.hostname
)
......@@ -97,7 +97,7 @@ class PipInstaller(BaseInstaller):
self.run(*args)
def update(self, package, target): # type: ("Package", "Package") -> None
def update(self, package: "Package", target: "Package") -> None:
if package.source_type != target.source_type:
# If the source type has changed, we remove the current
# package to avoid perpetual updates in some cases
......@@ -105,7 +105,7 @@ class PipInstaller(BaseInstaller):
self.install(target, update=True)
def remove(self, package): # type: ("Package") -> None
def remove(self, package: "Package") -> None:
try:
self.run("uninstall", package.name, "-y")
except CalledProcessError as e:
......@@ -127,10 +127,10 @@ class PipInstaller(BaseInstaller):
if src_dir.exists():
safe_rmtree(str(src_dir))
def run(self, *args, **kwargs): # type: (*Any,**Any) -> str
def run(self, *args: Any, **kwargs: Any) -> str:
return self._env.run_pip(*args, **kwargs)
def requirement(self, package, formatted=False): # type: ("Package", bool) -> str
def requirement(self, package: "Package", formatted: bool = False) -> str:
if formatted and not package.source_type:
req = "{}=={}".format(package.name, package.version)
for f in package.files:
......@@ -171,7 +171,7 @@ class PipInstaller(BaseInstaller):
return "{}=={}".format(package.name, package.version)
def create_temporary_requirement(self, package): # type: ("Package") -> str
def create_temporary_requirement(self, package: "Package") -> str:
fd, name = tempfile.mkstemp(
"reqs.txt", "{}-{}".format(package.name, package.version)
)
......@@ -183,7 +183,7 @@ class PipInstaller(BaseInstaller):
return name
def install_directory(self, package): # type: ("Package") -> Union[str, int]
def install_directory(self, package: "Package") -> Union[str, int]:
from cleo.io.null_io import NullIO
from poetry.factory import Factory
......@@ -241,7 +241,7 @@ class PipInstaller(BaseInstaller):
return self.run(*args)
def install_git(self, package): # type: ("Package") -> None
def install_git(self, package: "Package") -> None:
from poetry.core.packages import Package
from poetry.core.vcs import Git
......
......@@ -15,7 +15,7 @@ class ValidationError(ValueError):
pass
def validate_object(obj, schema_name): # type: (dict, str) -> List[str]
def validate_object(obj: dict, schema_name: str) -> List[str]:
schema = os.path.join(SCHEMA_DIR, "{}.json".format(schema_name))
if not os.path.exists(schema):
......
......@@ -8,7 +8,7 @@ from .standard import StandardLayout
_LAYOUTS = {"src": SrcLayout, "standard": StandardLayout}
def layout(name): # type: (str) -> Type[Layout]
def layout(name: str) -> Type[Layout]:
if name not in _LAYOUTS:
raise ValueError("Invalid layout")
......
......@@ -10,8 +10,9 @@ from poetry.utils.helpers import module_name
if TYPE_CHECKING:
from poetry.core.pyproject.toml import PyProjectTOML # noqa
from poetry.utils._compat import Path # noqa
from pathlib import Path
from poetry.core.pyproject.toml import PyProjectTOML
TESTS_DEFAULT = u"""from {package_name} import __version__
......@@ -47,21 +48,21 @@ license = ""
"""
BUILD_SYSTEM_MIN_VERSION = "1.0.0"
BUILD_SYSTEM_MAX_VERSION = None # type: Optional[str]
BUILD_SYSTEM_MAX_VERSION: Optional[str] = None
class Layout(object):
def __init__(
self,
project, # type: str
version="0.1.0", # type: str
description="", # type: str
readme_format="md", # type: str
author=None, # type: Optional[str]
license=None, # type: Optional[str]
python="*", # type: str
dependencies=None, # type: Optional[Dict[str, str]]
dev_dependencies=None, # type: Optional[Dict[str, str]]
project: str,
version: str = "0.1.0",
description: str = "",
readme_format: str = "md",
author: Optional[str] = None,
license: Optional[str] = None,
python: str = "*",
dependencies: Optional[Dict[str, str]] = None,
dev_dependencies: Optional[Dict[str, str]] = None,
):
self._project = project
self._package_name = module_name(project)
......@@ -78,7 +79,7 @@ class Layout(object):
self._author = author
def create(self, path, with_tests=True): # type: (Path, bool) -> None
def create(self, path: "Path", with_tests: bool = True) -> None:
path.mkdir(parents=True, exist_ok=True)
self._create_default(path)
......@@ -90,8 +91,8 @@ class Layout(object):
self._write_poetry(path)
def generate_poetry_content(
self, original=None
): # type: (Optional["PyProjectTOML"]) -> str
self, original: Optional["PyProjectTOML"] = None
) -> str:
template = POETRY_DEFAULT
if self._license:
template = POETRY_WITH_LICENSE
......@@ -131,10 +132,10 @@ class Layout(object):
return content
def _create_default(self, path, src=True): # type: (Path, bool) -> None
def _create_default(self, path: "Path", src: bool = True) -> None:
raise NotImplementedError()
def _create_readme(self, path): # type: (Path) -> None
def _create_readme(self, path: "Path") -> None:
if self._readme_format == "rst":
readme_file = path / "README.rst"
else:
......@@ -142,7 +143,7 @@ class Layout(object):
readme_file.touch()
def _create_tests(self, path): # type: (Path) -> None
def _create_tests(self, path: "Path") -> None:
tests = path / "tests"
tests_init = tests / "__init__.py"
tests_default = tests / "test_{}.py".format(self._package_name)
......@@ -157,7 +158,7 @@ class Layout(object):
)
)
def _write_poetry(self, path): # type: ("Path") -> None
def _write_poetry(self, path: "Path") -> None:
content = self.generate_poetry_content()
poetry = path / "pyproject.toml"
......
......@@ -6,14 +6,14 @@ from .layout import Layout
if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa
from pathlib import Path
DEFAULT = u"""__version__ = '{version}'
"""
class SrcLayout(Layout):
def _create_default(self, path): # type: ("Path") -> None
def _create_default(self, path: "Path") -> None:
package_path = path / "src" / self._package_name
package_init = package_path / "__init__.py"
......
......@@ -6,13 +6,13 @@ from .layout import Layout
if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa
from pathlib import Path
DEFAULT = u"""__version__ = '{version}'
"""
class StandardLayout(Layout):
def _create_default(self, path): # type: ("Path") -> None
def _create_default(self, path: "Path") -> None:
package_path = path / self._package_name
package_init = package_path / "__init__.py"
......
......@@ -21,8 +21,8 @@ from poetry.utils.helpers import is_dir_writable
if TYPE_CHECKING:
from cleo.io.io import IO # noqa
from poetry.core.poetry import Poetry # noqa
from poetry.utils.env import Env # noqa
from poetry.core.poetry import Poetry
from poetry.utils.env import Env
SCRIPT_TEMPLATE = """\
#!{python}
......@@ -38,13 +38,13 @@ WINDOWS_CMD_TEMPLATE = """\
class EditableBuilder(Builder):
def __init__(self, poetry, env, io): # type: ("Poetry", "Env", "IO") -> None
def __init__(self, poetry: "Poetry", env: "Env", io: "IO") -> None:
super(EditableBuilder, self).__init__(poetry)
self._env = env
self._io = io
def build(self): # type: () -> None
def build(self) -> None:
self._debug(
" - Building package <c1>{}</c1> in <info>editable</info> mode".format(
self._package.name
......@@ -66,11 +66,11 @@ class EditableBuilder(Builder):
added_files += self._add_scripts()
self._add_dist_info(added_files)
def _run_build_script(self, build_script): # type: (Path) -> None
def _run_build_script(self, build_script: Path) -> None:
self._debug(" - Executing build script: <b>{}</b>".format(build_script))
self._env.run("python", str(self._path.joinpath(build_script)), call=True)
def _setup_build(self): # type: () -> None
def _setup_build(self) -> None:
builder = SdistBuilder(self._poetry)
setup = self._path / "setup.py"
has_setup = setup.exists()
......@@ -102,7 +102,7 @@ class EditableBuilder(Builder):
if not has_setup:
os.remove(str(setup))
def _add_pth(self): # type: () -> List[Path]
def _add_pth(self) -> List[Path]:
paths = set()
for include in self._module.includes:
if isinstance(include, PackageInclude) and (
......@@ -127,14 +127,14 @@ class EditableBuilder(Builder):
return [pth_file]
except OSError:
# TODO: Replace with PermissionError
self._io.error_line(
self._io.write_error_line(
" - Failed to create <c2>{}</c2> for {}".format(
pth_file.name, self._poetry.file.parent
)
)
return []
def _add_scripts(self): # type: () -> List[Path]
def _add_scripts(self) -> List[Path]:
added = []
entry_points = self.convert_entry_points()
......@@ -142,7 +142,7 @@ class EditableBuilder(Builder):
if is_dir_writable(path=scripts_path, create=True):
break
else:
self._io.error_line(
self._io.write_error_line(
" - Failed to find a suitable script installation directory for {}".format(
self._poetry.file.parent
)
......@@ -193,7 +193,7 @@ class EditableBuilder(Builder):
return added
def _add_dist_info(self, added_files): # type: (List[Path]) -> None
def _add_dist_info(self, added_files: List[Path]) -> None:
from poetry.core.masonry.builders.wheel import WheelBuilder
added_files = added_files[:]
......@@ -247,7 +247,7 @@ class EditableBuilder(Builder):
# RECORD itself is recorded with no hash or size
f.write("{},,\n".format(dist_info.joinpath("RECORD")))
def _get_file_hash(self, filepath): # type: (Path) -> str
def _get_file_hash(self, filepath: Path) -> str:
hashsum = hashlib.sha256()
with filepath.open("rb") as src:
while True:
......@@ -260,6 +260,6 @@ class EditableBuilder(Builder):
return urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=")
def _debug(self, msg): # type: (str) -> None
def _debug(self, msg: str) -> None:
if self._io.is_debug():
self._io.write_line(msg)
......@@ -6,16 +6,19 @@ from .version_solver import VersionSolver
if TYPE_CHECKING:
from poetry.core.packages import DependencyPackage # noqa
from poetry.core.packages import ProjectPackage # noqa
from poetry.puzzle.provider import Provider # noqa
from poetry.core.packages import ProjectPackage
from poetry.packages import DependencyPackage
from poetry.puzzle.provider import Provider
from .result import SolverResult # noqa
from .result import SolverResult
def resolve_version(
root, provider, locked=None, use_latest=None
): # type: ("ProjectPackage", "Provider", Dict[str, "DependencyPackage"],List[str]) -> "SolverResult"
root: "ProjectPackage",
provider: "Provider",
locked: Dict[str, "DependencyPackage"] = None,
use_latest: List[str] = None,
) -> "SolverResult":
solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
return solver.solve()
......@@ -6,10 +6,10 @@ from .term import Term
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
from .incompatibility import Incompatibility # noqa
from .incompatibility import Incompatibility
class Assignment(Term):
......@@ -18,8 +18,13 @@ class Assignment(Term):
"""
def __init__(
self, dependency, is_positive, decision_level, index, cause=None
): # type: ("Dependency", bool, int, int, Optional["Incompatibility"]) -> None
self,
dependency: "Dependency",
is_positive: bool,
decision_level: int,
index: int,
cause: Optional["Incompatibility"] = None,
) -> None:
super(Assignment, self).__init__(dependency, is_positive)
self._decision_level = decision_level
......@@ -27,28 +32,33 @@ class Assignment(Term):
self._cause = cause
@property
def decision_level(self): # type: () -> int
def decision_level(self) -> int:
return self._decision_level
@property
def index(self): # type: () -> int
def index(self) -> int:
return self._index
@property
def cause(self): # type: () -> "Incompatibility"
def cause(self) -> "Incompatibility":
return self._cause
@classmethod
def decision(
cls, package, decision_level, index
): # type: ("Package", int, int) -> Assignment
cls, package: "Package", decision_level: int, index: int
) -> "Assignment":
return cls(package.to_dependency(), True, decision_level, index)
@classmethod
def derivation(
cls, dependency, is_positive, cause, decision_level, index
): # type: (Any, bool, "Incompatibility", int, int) -> "Assignment"
cls,
dependency: Any,
is_positive: bool,
cause: "Incompatibility",
decision_level: int,
index: int,
) -> "Assignment":
return cls(dependency, is_positive, decision_level, index, cause)
def is_decision(self): # type: () -> bool
def is_decision(self) -> bool:
return self._cause is None
......@@ -11,27 +11,27 @@ from .incompatibility_cause import PythonCause
class SolveFailure(Exception):
def __init__(self, incompatibility): # type: (Incompatibility) -> None
def __init__(self, incompatibility: Incompatibility) -> None:
self._incompatibility = incompatibility
@property
def message(self): # type: () -> str
def message(self) -> str:
return str(self)
def __str__(self): # type: () -> str
def __str__(self) -> str:
return _Writer(self._incompatibility).write()
class _Writer:
def __init__(self, root): # type: (Incompatibility) -> None
def __init__(self, root: Incompatibility) -> None:
self._root = root
self._derivations = {} # type: Dict[Incompatibility, int]
self._lines = [] # type: List[Tuple[str, Optional[int]]]
self._line_numbers = {} # type: Dict[Incompatibility, int]
self._derivations: Dict[Incompatibility, int] = {}
self._lines: List[Tuple[str, Optional[int]]] = []
self._line_numbers: Dict[Incompatibility, int] = {}
self._count_derivations(self._root)
def write(self): # type: () -> str
def write(self) -> str:
buffer = []
required_python_version_notification = False
......@@ -98,8 +98,8 @@ class _Writer:
return "\n".join(buffer)
def _write(
self, incompatibility, message, numbered=False
): # type: (Incompatibility, str, bool) -> None
self, incompatibility: Incompatibility, message: str, numbered: bool = False
) -> None:
if numbered:
number = len(self._line_numbers) + 1
self._line_numbers[incompatibility] = number
......@@ -108,8 +108,11 @@ class _Writer:
self._lines.append((message, None))
def _visit(
self, incompatibility, details_for_incompatibility, conclusion=False
): # type: (Incompatibility, Dict, bool) -> None
self,
incompatibility: Incompatibility,
details_for_incompatibility: Dict,
conclusion: bool = False,
) -> None:
numbered = conclusion or self._derivations[incompatibility] > 1
conjunction = "So," if conclusion or incompatibility == self._root else "And"
incompatibility_string = str(incompatibility)
......@@ -208,7 +211,7 @@ class _Writer:
numbered=numbered,
)
elif self._is_collapsible(derived):
derived_cause = derived.cause # type: ConflictCause
derived_cause: ConflictCause = derived.cause
if isinstance(derived_cause.conflict.cause, ConflictCause):
collapsed_derived = derived_cause.conflict
else:
......@@ -252,11 +255,11 @@ class _Writer:
numbered=numbered,
)
def _is_collapsible(self, incompatibility): # type: (Incompatibility) -> bool
def _is_collapsible(self, incompatibility: Incompatibility) -> bool:
if self._derivations[incompatibility] > 1:
return False
cause = incompatibility.cause # type: ConflictCause
cause: ConflictCause = incompatibility.cause
if isinstance(cause.conflict.cause, ConflictCause) and isinstance(
cause.other.cause, ConflictCause
):
......@@ -275,12 +278,12 @@ class _Writer:
return complex not in self._line_numbers
def _is_single_line(self, cause): # type: (ConflictCause) -> bool
def _is_single_line(self, cause: ConflictCause) -> bool:
return not isinstance(cause.conflict.cause, ConflictCause) and not isinstance(
cause.other.cause, ConflictCause
)
def _count_derivations(self, incompatibility): # type: (Incompatibility) -> None
def _count_derivations(self, incompatibility: Incompatibility) -> None:
if incompatibility in self._derivations:
self._derivations[incompatibility] += 1
else:
......
from typing import Dict
from typing import Generator
from typing import Iterator
from typing import List
from typing import Optional
from typing import Union
......@@ -16,9 +16,7 @@ from .term import Term
class Incompatibility:
def __init__(
self, terms, cause
): # type: (List[Term], IncompatibilityCause) -> None
def __init__(self, terms: List[Term], cause: IncompatibilityCause) -> None:
# Remove the root package from generated incompatibilities, since it will
# always be satisfied. This makes error reporting clearer, and may also
# make solving more efficient.
......@@ -43,7 +41,7 @@ class Incompatibility:
pass
else:
# Coalesce multiple terms about the same package if possible.
by_name = {} # type: Dict[str, Dict[str, Term]]
by_name: Dict[str, Dict[str, Term]] = {}
for term in terms:
if term.dependency.complete_name not in by_name:
by_name[term.dependency.complete_name] = {}
......@@ -80,25 +78,33 @@ class Incompatibility:
self._cause = cause
@property
def terms(self): # type: () -> List[Term]
def terms(self) -> List[Term]:
return self._terms
@property
def cause(
self,
): # type: () -> Union[RootCause, NoVersionsCause, DependencyCause, ConflictCause, PythonCause, PlatformCause, PackageNotFoundCause]
) -> Union[
RootCause,
NoVersionsCause,
DependencyCause,
ConflictCause,
PythonCause,
PlatformCause,
PackageNotFoundCause,
]:
return self._cause
@property
def external_incompatibilities(
self,
): # type: () -> Generator[Union[ConflictCause, Incompatibility]]
) -> Iterator[Union[ConflictCause, "Incompatibility"]]:
"""
Returns all external incompatibilities in this incompatibility's
derivation graph.
"""
if isinstance(self._cause, ConflictCause):
cause = self._cause # type: ConflictCause
cause: ConflictCause = self._cause
for incompatibility in cause.conflict.external_incompatibilities:
yield incompatibility
......@@ -107,12 +113,12 @@ class Incompatibility:
else:
yield self
def is_failure(self): # type: () -> bool
def is_failure(self) -> bool:
return len(self._terms) == 0 or (
len(self._terms) == 1 and self._terms[0].dependency.is_root
)
def __str__(self): # type: () -> str
def __str__(self) -> str:
if isinstance(self._cause, DependencyCause):
assert len(self._terms) == 2
......@@ -128,7 +134,7 @@ class Incompatibility:
assert len(self._terms) == 1
assert self._terms[0].is_positive()
cause = self._cause # type: PythonCause
cause: PythonCause = self._cause
text = "{} requires ".format(self._terse(self._terms[0], allow_every=True))
text += "Python {}".format(cause.python_version)
......@@ -137,7 +143,7 @@ class Incompatibility:
assert len(self._terms) == 1
assert self._terms[0].is_positive()
cause = self._cause # type: PlatformCause
cause: PlatformCause = self._cause
text = "{} requires ".format(self._terse(self._terms[0], allow_every=True))
text += "platform {}".format(cause.platform)
......@@ -227,8 +233,12 @@ class Incompatibility:
return "one of {} must be true".format(" or ".join(negative))
def and_to_string(
self, other, details, this_line, other_line
): # type: (Incompatibility, dict, Optional[int], Optional[int]) -> str
self,
other: "Incompatibility",
details: dict,
this_line: Optional[int],
other_line: Optional[int],
) -> str:
requires_both = self._try_requires_both(other, details, this_line, other_line)
if requires_both is not None:
return requires_both
......@@ -257,8 +267,12 @@ class Incompatibility:
return "\n".join(buffer)
def _try_requires_both(
self, other, details, this_line, other_line
): # type: (Incompatibility, dict, Optional[int], Optional[int]) -> Optional[str]
self,
other: "Incompatibility",
details: dict,
this_line: Optional[int],
other_line: Optional[int],
) -> Optional[str]:
if len(self._terms) == 1 or len(other.terms) == 1:
return
......@@ -303,8 +317,8 @@ class Incompatibility:
return "".join(buffer)
def _try_requires_through(
self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> Optional[str]
self, other: "Incompatibility", details: dict, this_line: int, other_line: int
) -> Optional[str]:
if len(self._terms) == 1 or len(other.terms) == 1:
return
......@@ -381,8 +395,8 @@ class Incompatibility:
return "".join(buffer)
def _try_requires_forbidden(
self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> Optional[str]
self, other: "Incompatibility", details: dict, this_line: int, other_line: int
) -> Optional[str]:
if len(self._terms) != 1 and len(other.terms) != 1:
return None
......@@ -422,7 +436,7 @@ class Incompatibility:
buffer.append("({}) ".format(prior_line))
if isinstance(latter.cause, PythonCause):
cause = latter.cause # type: PythonCause
cause: PythonCause = latter.cause
buffer.append("which requires Python {}".format(cause.python_version))
elif isinstance(latter.cause, NoVersionsCause):
buffer.append("which doesn't match any versions")
......@@ -436,13 +450,13 @@ class Incompatibility:
return "".join(buffer)
def _terse(self, term, allow_every=False): # type: (Term, bool) -> str
def _terse(self, term: Term, allow_every: bool = False) -> str:
if allow_every and term.constraint.is_any():
return "every version of {}".format(term.dependency.complete_name)
return str(term.dependency)
def _single_term_where(self, callable): # type: (callable) -> Optional[Term]
def _single_term_where(self, callable: callable) -> Optional[Term]:
found = None
for term in self._terms:
if not callable(term):
......@@ -455,5 +469,5 @@ class Incompatibility:
return found
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return "<Incompatibility {}>".format(str(self))
......@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from poetry.mixology.incompatibility import Incompatibility # noqa
from poetry.mixology.incompatibility import Incompatibility
class IncompatibilityCause(Exception):
......@@ -32,21 +32,19 @@ class ConflictCause(IncompatibilityCause):
during conflict resolution.
"""
def __init__(
self, conflict, other
): # type: ("Incompatibility", "Incompatibility") -> None
def __init__(self, conflict: "Incompatibility", other: "Incompatibility") -> None:
self._conflict = conflict
self._other = other
@property
def conflict(self): # type: () -> "Incompatibility"
def conflict(self) -> "Incompatibility":
return self._conflict
@property
def other(self): # type: () -> "Incompatibility"
def other(self) -> "Incompatibility":
return self._other
def __str__(self): # type: () -> str
def __str__(self) -> str:
return str(self._conflict)
......@@ -57,16 +55,16 @@ class PythonCause(IncompatibilityCause):
with the current python version.
"""
def __init__(self, python_version, root_python_version): # type: (str, str) -> None
def __init__(self, python_version: str, root_python_version: str) -> None:
self._python_version = python_version
self._root_python_version = root_python_version
@property
def python_version(self): # type: () -> str
def python_version(self) -> str:
return self._python_version
@property
def root_python_version(self): # type: () -> str
def root_python_version(self) -> str:
return self._root_python_version
......@@ -76,11 +74,11 @@ class PlatformCause(IncompatibilityCause):
(OS most likely) being incompatible with the current platform.
"""
def __init__(self, platform): # type: (str) -> None
def __init__(self, platform: str) -> None:
self._platform = platform
@property
def platform(self): # type: () -> str
def platform(self) -> str:
return self._platform
......@@ -90,9 +88,9 @@ class PackageNotFoundCause(IncompatibilityCause):
source.
"""
def __init__(self, error): # type: (Exception) -> None
def __init__(self, error: Exception) -> None:
self._error = error
@property
def error(self): # type: () -> Exception
def error(self) -> Exception:
return self._error
......@@ -9,9 +9,8 @@ from .term import Term
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.packages import DependencyPackage # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
class PartialSolution:
......@@ -23,19 +22,19 @@ class PartialSolution:
# See https://github.com/dart-lang/mixology/tree/master/doc/solver.md#partial-solution.
"""
def __init__(self): # type: () -> None
def __init__(self) -> None:
# The assignments that have been made so far, in the order they were
# assigned.
self._assignments = [] # type: List[Assignment]
self._assignments: List[Assignment] = []
# The decisions made for each package.
self._decisions = dict() # type: Dict[str, "Package"]
self._decisions: Dict[str, "Package"] = dict()
# The intersection of all positive Assignments for each package, minus any
# negative Assignments that refer to that package.
#
# This is derived from self._assignments.
self._positive = dict() # type: Dict[str, Term]
self._positive: Dict[str, Term] = dict()
# The union of all negative Assignments for each package.
#
......@@ -43,7 +42,7 @@ class PartialSolution:
# map.
#
# This is derived from self._assignments.
self._negative = dict() # type: Dict[str, Dict[str, Term]]
self._negative: Dict[str, Dict[str, Term]] = dict()
# The number of distinct solutions that have been attempted so far.
self._attempted_solutions = 1
......@@ -52,26 +51,26 @@ class PartialSolution:
self._backtracking = False
@property
def decisions(self): # type: () -> List["Package"]
def decisions(self) -> List["Package"]:
return list(self._decisions.values())
@property
def decision_level(self): # type: () -> int
def decision_level(self) -> int:
return len(self._decisions)
@property
def attempted_solutions(self): # type: () -> int
def attempted_solutions(self) -> int:
return self._attempted_solutions
@property
def unsatisfied(self): # type: () -> List["Dependency"]
def unsatisfied(self) -> List["Dependency"]:
return [
term.dependency
for term in self._positive.values()
if term.dependency.complete_name not in self._decisions
]
def decide(self, package): # type: ("Package") -> None
def decide(self, package: "Package") -> None:
"""
Adds an assignment of package as a decision
and increments the decision level.
......@@ -91,8 +90,8 @@ class PartialSolution:
)
def derive(
self, dependency, is_positive, cause
): # type: ("Dependency", bool, Incompatibility) -> None
self, dependency: "Dependency", is_positive: bool, cause: Incompatibility
) -> None:
"""
Adds an assignment of package as a derivation.
"""
......@@ -106,14 +105,14 @@ class PartialSolution:
)
)
def _assign(self, assignment): # type: (Assignment) -> None
def _assign(self, assignment: Assignment) -> None:
"""
Adds an Assignment to _assignments and _positive or _negative.
"""
self._assignments.append(assignment)
self._register(assignment)
def backtrack(self, decision_level): # type: (int) -> None
def backtrack(self, decision_level: int) -> None:
"""
Resets the current decision level to decision_level, and removes all
assignments made after that level.
......@@ -139,7 +138,7 @@ class PartialSolution:
if assignment.dependency.complete_name in packages:
self._register(assignment)
def _register(self, assignment): # type: (Assignment) -> None
def _register(self, assignment: Assignment) -> None:
"""
Registers an Assignment in _positive or _negative.
"""
......@@ -169,7 +168,7 @@ class PartialSolution:
self._negative[name][ref] = term
def satisfier(self, term): # type: (Term) -> Assignment
def satisfier(self, term: Term) -> Assignment:
"""
Returns the first Assignment in this solution such that the sublist of
assignments up to and including that entry collectively satisfies term.
......@@ -202,10 +201,10 @@ class PartialSolution:
raise RuntimeError("[BUG] {} is not satisfied.".format(term))
def satisfies(self, term): # type: (Term) -> bool
def satisfies(self, term: Term) -> bool:
return self.relation(term) == SetRelation.SUBSET
def relation(self, term): # type: (Term) -> int
def relation(self, term: Term) -> int:
positive = self._positive.get(term.dependency.complete_name)
if positive is not None:
return positive.relation(term)
......
......@@ -3,22 +3,25 @@ from typing import List
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import ProjectPackage # noqa
from poetry.core.packages import Package
from poetry.core.packages import ProjectPackage
class SolverResult:
def __init__(
self, root, packages, attempted_solutions
): # type: ("ProjectPackage", List["Package"], int) -> None
self,
root: "ProjectPackage",
packages: List["Package"],
attempted_solutions: int,
) -> None:
self._root = root
self._packages = packages
self._attempted_solutions = attempted_solutions
@property
def packages(self): # type: () -> List["Package"]
def packages(self) -> List["Package"]:
return self._packages
@property
def attempted_solutions(self): # type: () -> int
def attempted_solutions(self) -> int:
return self._attempted_solutions
......@@ -7,7 +7,7 @@ from crashtest.contracts.solution import Solution
class PythonRequirementSolutionProvider(HasSolutionsForException):
def can_solve(self, exception): # type: (Exception) -> bool
def can_solve(self, exception: Exception) -> bool:
from poetry.puzzle.exceptions import SolverProblemError
if not isinstance(exception, SolverProblemError):
......@@ -24,7 +24,7 @@ class PythonRequirementSolutionProvider(HasSolutionsForException):
return True
def get_solutions(self, exception): # type: (Exception) -> List[Solution]
def get_solutions(self, exception: Exception) -> List[Solution]:
from ..solutions.python_requirement_solution import PythonRequirementSolution
return [PythonRequirementSolution(exception)]
......@@ -5,11 +5,11 @@ from crashtest.contracts.solution import Solution
if TYPE_CHECKING:
from poetry.mixology.incompatibility_cause import PackageNotFoundCause # noqa
from poetry.mixology.incompatibility_cause import PackageNotFoundCause
class PythonRequirementSolution(Solution):
def __init__(self, exception): # type: ("PackageNotFoundCause") -> None
def __init__(self, exception: "PackageNotFoundCause") -> None:
from poetry.core.semver import parse_constraint
from poetry.mixology.incompatibility_cause import PythonCause
......@@ -44,15 +44,15 @@ class PythonRequirementSolution(Solution):
self._description = description
@property
def solution_title(self): # type: () -> str
def solution_title(self) -> str:
return self._title
@property
def solution_description(self): # type: () -> str
def solution_description(self) -> str:
return self._description
@property
def documentation_links(self): # type: () -> List[str]
def documentation_links(self) -> List[str]:
return [
"https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies",
"https://python-poetry.org/docs/dependency-specification/#using-environment-markers",
......
......@@ -8,7 +8,7 @@ from .set_relation import SetRelation
if TYPE_CHECKING:
from poetry.core.semver import VersionTypes # noqa
from poetry.core.semver import VersionTypes
class Term(object):
......@@ -19,26 +19,26 @@ class Term(object):
See https://github.com/dart-lang/pub/tree/master/doc/solver.md#term.
"""
def __init__(self, dependency, is_positive): # type: (Dependency, bool) -> None
def __init__(self, dependency: Dependency, is_positive: bool) -> None:
self._dependency = dependency
self._positive = is_positive
@property
def inverse(self): # type: () -> Term
def inverse(self) -> "Term":
return Term(self._dependency, not self.is_positive())
@property
def dependency(self): # type: () -> Dependency
def dependency(self) -> Dependency:
return self._dependency
@property
def constraint(self): # type: () -> "VersionTypes"
def constraint(self) -> "VersionTypes":
return self._dependency.constraint
def is_positive(self): # type: () -> bool
def is_positive(self) -> bool:
return self._positive
def satisfies(self, other): # type: (Term) -> bool
def satisfies(self, other: "Term") -> bool:
"""
Returns whether this term satisfies another.
"""
......@@ -47,7 +47,7 @@ class Term(object):
and self.relation(other) == SetRelation.SUBSET
)
def relation(self, other): # type: (Term) -> int
def relation(self, other: "Term") -> int:
"""
Returns the relationship between the package versions
allowed by this term and another.
......@@ -111,7 +111,7 @@ class Term(object):
# not foo ^1.5.0 is a superset of not foo ^1.0.0
return SetRelation.OVERLAPPING
def intersect(self, other): # type: (Term) -> Optional[Term]
def intersect(self, other: "Term") -> Optional["Term"]:
"""
Returns a Term that represents the packages
allowed by both this term and another
......@@ -145,14 +145,14 @@ class Term(object):
else:
return
def difference(self, other): # type: (Term) -> Term
def difference(self, other: "Term") -> "Term":
"""
Returns a Term that represents packages
allowed by this term and not by the other
"""
return self.intersect(other.inverse)
def _compatible_dependency(self, other): # type: (Term) -> bool
def _compatible_dependency(self, other: "Dependency") -> bool:
return (
self.dependency.is_root
or other.is_root
......@@ -160,15 +160,15 @@ class Term(object):
)
def _non_empty_term(
self, constraint, is_positive
): # type: ("VersionTypes", bool) -> Optional[Term]
self, constraint: "VersionTypes", is_positive: bool
) -> Optional["Term"]:
if constraint.is_empty():
return
return Term(self.dependency.with_constraint(constraint), is_positive)
def __str__(self): # type: () -> str
def __str__(self) -> str:
return "{}{}".format("not " if not self.is_positive() else "", self._dependency)
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return "<Term {}>".format(str(self))
......@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from typing import Optional
from typing import Union
from poetry.core.packages import Dependency
from poetry.core.packages import Package
......@@ -40,10 +41,10 @@ class VersionSolver:
def __init__(
self,
root, # type: ProjectPackage
provider, # type: Provider
locked=None, # type: Dict[str, Package]
use_latest=None, # type: List[str]
root: ProjectPackage,
provider: "Provider",
locked: Dict[str, Package] = None,
use_latest: List[str] = None,
):
self._root = root
self._provider = provider
......@@ -54,14 +55,14 @@ class VersionSolver:
self._use_latest = use_latest
self._incompatibilities = {} # type: Dict[str, List[Incompatibility]]
self._incompatibilities: Dict[str, List[Incompatibility]] = {}
self._solution = PartialSolution()
@property
def solution(self): # type: () -> PartialSolution
def solution(self) -> PartialSolution:
return self._solution
def solve(self): # type: () -> SolverResult
def solve(self) -> SolverResult:
"""
Finds a set of dependencies that match the root package's constraints,
or raises an error if no such set is available.
......@@ -91,7 +92,7 @@ class VersionSolver:
)
)
def _propagate(self, package): # type: (str) -> None
def _propagate(self, package: str) -> None:
"""
Performs unit propagation on incompatibilities transitively
related to package to derive new assignments for _solution.
......@@ -129,8 +130,8 @@ class VersionSolver:
changed.add(result)
def _propagate_incompatibility(
self, incompatibility
): # type: (Incompatibility) -> Optional[str, _conflict]
self, incompatibility: Incompatibility
) -> Optional[Union[str, object]]:
"""
If incompatibility is almost satisfied by _solution, adds the
negation of the unsatisfied term to _solution.
......@@ -182,9 +183,7 @@ class VersionSolver:
return unsatisfied.dependency.complete_name
def _resolve_conflict(
self, incompatibility
): # type: (Incompatibility) -> Incompatibility
def _resolve_conflict(self, incompatibility: Incompatibility) -> Incompatibility:
"""
Given an incompatibility that's satisfied by _solution,
The `conflict resolution`_ constructs a new incompatibility that encapsulates the root
......@@ -317,7 +316,7 @@ class VersionSolver:
raise SolveFailure(incompatibility)
def _choose_package_version(self): # type: () -> Optional[str]
def _choose_package_version(self) -> Optional[str]:
"""
Tries to select a version of a required package.
......@@ -331,7 +330,7 @@ class VersionSolver:
# Prefer packages with as few remaining versions as possible,
# so that if a conflict is necessary it's forced quickly.
def _get_min(dependency): # type: (Dependency) -> int
def _get_min(dependency: Dependency) -> int:
if dependency.name in self._use_latest:
# If we're forced to use the latest version of a package, it effectively
# only has one version to choose from.
......@@ -418,7 +417,7 @@ class VersionSolver:
return dependency.complete_name
def _result(self): # type: () -> SolverResult
def _result(self) -> SolverResult:
"""
Creates a #SolverResult from the decisions in _solution
"""
......@@ -430,7 +429,7 @@ class VersionSolver:
self._solution.attempted_solutions,
)
def _add_incompatibility(self, incompatibility): # type: (Incompatibility) -> None
def _add_incompatibility(self, incompatibility: Incompatibility) -> None:
self._log("fact: {}".format(incompatibility))
for term in incompatibility.terms:
......@@ -447,7 +446,7 @@ class VersionSolver:
incompatibility
)
def _get_locked(self, dependency): # type: (Dependency) -> Optional[Package]
def _get_locked(self, dependency: Dependency) -> Optional[Package]:
if dependency.name in self._use_latest:
return
......@@ -460,5 +459,5 @@ class VersionSolver:
return locked
def _log(self, text): # type: (str) -> None
def _log(self, text: str) -> None:
self._provider.debug(text, self._solution.attempted_solutions)
......@@ -7,46 +7,46 @@ from poetry.core.packages.package import Package
class DependencyPackage(object):
def __init__(self, dependency, package): # type: (Dependency, Package) -> None
def __init__(self, dependency: Dependency, package: Package) -> None:
self._dependency = dependency
self._package = package
@property
def dependency(self): # type: () -> Dependency
def dependency(self) -> Dependency:
return self._dependency
@property
def package(self): # type: () -> Package
def package(self) -> Package:
return self._package
def clone(self): # type: () -> "DependencyPackage"
def clone(self) -> "DependencyPackage":
return self.__class__(self._dependency, self._package.clone())
def with_features(self, features): # type: (List[str]) -> "DependencyPackage"
def with_features(self, features: List[str]) -> "DependencyPackage":
return self.__class__(self._dependency, self._package.with_features(features))
def without_features(self): # type: () -> "DependencyPackage"
def without_features(self) -> "DependencyPackage":
return self.with_features([])
def __getattr__(self, name): # type: (str) -> Any
def __getattr__(self, name: str) -> Any:
return getattr(self._package, name)
def __setattr__(self, key, value): # type: (str, Any) -> None
def __setattr__(self, key: str, value: Any) -> None:
if key in {"_dependency", "_package"}:
return super(DependencyPackage, self).__setattr__(key, value)
setattr(self._package, key, value)
def __str__(self): # type: () -> str
def __str__(self) -> str:
return str(self._package)
def __repr__(self): # type: () -> str
def __repr__(self) -> str:
return repr(self._package)
def __hash__(self): # type: () -> int
def __hash__(self) -> int:
return hash(self._package)
def __eq__(self, other): # type: (Union[Package, "DependencyPackage"]) -> bool
def __eq__(self, other: Union[Package, "DependencyPackage"]) -> bool:
if isinstance(other, DependencyPackage):
other = other.package
......
......@@ -39,7 +39,7 @@ from poetry.utils.extras import get_extra_package_names
if TYPE_CHECKING:
from ptomlkit.toml_document import TOMLDocument # noqa
from tomlkit.toml_document import TOMLDocument
logger = logging.getLogger(__name__)
......@@ -50,24 +50,24 @@ class Locker(object):
_relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"]
def __init__(self, lock, local_config): # type: (Union[str, Path], dict) -> None
def __init__(self, lock: Union[str, Path], local_config: dict) -> None:
self._lock = TOMLFile(lock)
self._local_config = local_config
self._lock_data = None
self._content_hash = self._get_content_hash()
@property
def lock(self): # type: () -> TOMLFile
def lock(self) -> TOMLFile:
return self._lock
@property
def lock_data(self): # type: () -> TOMLDocument
def lock_data(self) -> "TOMLDocument":
if self._lock_data is None:
self._lock_data = self._get_lock_data()
return self._lock_data
def is_locked(self): # type: () -> bool
def is_locked(self) -> bool:
"""
Checks whether the locker has been locked (lockfile found).
"""
......@@ -76,7 +76,7 @@ class Locker(object):
return "package" in self.lock_data
def is_fresh(self): # type: () -> bool
def is_fresh(self) -> bool:
"""
Checks whether the lock file is still up to date with the current hash.
"""
......@@ -89,8 +89,8 @@ class Locker(object):
return False
def locked_repository(
self, with_dev_reqs=False
): # type: (bool) -> poetry.repositories.Repository
self, with_dev_reqs: bool = False
) -> poetry.repositories.Repository:
"""
Searches and returns a repository of locked packages.
"""
......@@ -202,8 +202,8 @@ class Locker(object):
@staticmethod
def __get_locked_package(
_dependency, packages_by_name
): # type: (Dependency, Dict[str, List[Package]]) -> Optional[Package]
_dependency: Dependency, packages_by_name: Dict[str, List[Package]]
) -> Optional[Package]:
"""
Internal helper to identify corresponding locked package using dependency
version constraints.
......@@ -216,13 +216,13 @@ class Locker(object):
@classmethod
def __walk_dependency_level(
cls,
dependencies,
level,
pinned_versions,
packages_by_name,
project_level_dependencies,
nested_dependencies,
): # type: (List[Dependency], int, bool, Dict[str, List[Package]], Set[str], Dict[Tuple[str, str], Dependency]) -> Dict[Tuple[str, str], Dependency]
dependencies: List[Dependency],
level: int,
pinned_versions: bool,
packages_by_name: Dict[str, List[Package]],
project_level_dependencies: Set[str],
nested_dependencies: Dict[Tuple[str, str], Dependency],
) -> Dict[Tuple[str, str], Dependency]:
if not dependencies:
return nested_dependencies
......@@ -284,8 +284,12 @@ class Locker(object):
@classmethod
def get_project_dependencies(
cls, project_requires, locked_packages, pinned_versions=False, with_nested=False
): # type: (List[Dependency], List[Package], bool, bool) -> Iterable[Dependency]
cls,
project_requires: List[Dependency],
locked_packages: List[Package],
pinned_versions: bool = False,
with_nested: bool = False,
) -> Iterable[Dependency]:
# group packages entries by name, this is required because requirement might use different constraints
packages_by_name = {}
for pkg in locked_packages:
......@@ -339,8 +343,11 @@ class Locker(object):
return sorted(nested_dependencies.values(), key=lambda x: x.name.lower())
def get_project_dependency_packages(
self, project_requires, dev=False, extras=None
): # type: (List[Dependency], bool, Optional[Union[bool, Sequence[str]]]) -> Iterator[DependencyPackage]
self,
project_requires: List[Dependency],
dev: bool = False,
extras: Optional[Union[bool, Sequence[str]]] = None,
) -> Iterator[DependencyPackage]:
repository = self.locked_repository(with_dev_reqs=dev)
# Build a set of all packages required by our selected extras
......@@ -388,7 +395,7 @@ class Locker(object):
yield DependencyPackage(dependency=dependency, package=package)
def set_lock_data(self, root, packages): # type: (Package, List[Package]) -> bool
def set_lock_data(self, root: Package, packages: List[Package]) -> bool:
files = table()
packages = self._lock_packages(packages)
# Retrieving hashes
......@@ -433,7 +440,7 @@ class Locker(object):
return False
def _write_lock_data(self, data): # type: ("TOMLDocument") -> None
def _write_lock_data(self, data: "TOMLDocument") -> None:
self.lock.write(data)
# Checking lock file data consistency
......@@ -442,7 +449,7 @@ class Locker(object):
self._lock_data = None
def _get_content_hash(self): # type: () -> str
def _get_content_hash(self) -> str:
"""
Returns the sha256 hash of the sorted content of the pyproject file.
"""
......@@ -458,7 +465,7 @@ class Locker(object):
return content_hash
def _get_lock_data(self): # type: () -> "TOMLDocument"
def _get_lock_data(self) -> "TOMLDocument":
if not self._lock.exists():
raise RuntimeError("No lockfile found. Unable to read locked packages")
......@@ -490,7 +497,7 @@ class Locker(object):
return lock_data
def _lock_packages(self, packages): # type: (List[Package]) -> list
def _lock_packages(self, packages: List[Package]) -> list:
locked = []
for package in sorted(packages, key=lambda x: x.name):
......@@ -500,7 +507,7 @@ class Locker(object):
return locked
def _dump_package(self, package): # type: (Package) -> dict
def _dump_package(self, package: Package) -> dict:
dependencies = {}
for dependency in sorted(package.requires, key=lambda d: d.name):
if dependency.pretty_name not in dependencies:
......
......@@ -6,14 +6,16 @@ from .dependency_package import DependencyPackage
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
class PackageCollection(list):
def __init__(
self, dependency, packages=None
): # type: (Dependency, List[Union["Package", DependencyPackage]]) -> None
self,
dependency: "Dependency",
packages: List[Union["Package", DependencyPackage]] = None,
) -> None:
self._dependency = dependency
if packages is None:
......@@ -24,7 +26,7 @@ class PackageCollection(list):
for package in packages:
self.append(package)
def append(self, package): # type: (Union["Package", DependencyPackage]) -> None
def append(self, package: Union["Package", DependencyPackage]) -> None:
if isinstance(package, DependencyPackage):
package = package.package
......
......@@ -18,11 +18,11 @@ class Poetry(BasePoetry):
def __init__(
self,
file, # type: Path
local_config, # type: dict
package, # type: ProjectPackage
locker, # type: Locker
config, # type: Config
file: Path,
local_config: dict,
package: ProjectPackage,
locker: Locker,
config: Config,
):
super(Poetry, self).__init__(file, local_config, package)
......@@ -31,28 +31,28 @@ class Poetry(BasePoetry):
self._pool = Pool()
@property
def locker(self): # type: () -> Locker
def locker(self) -> Locker:
return self._locker
@property
def pool(self): # type: () -> Pool
def pool(self) -> Pool:
return self._pool
@property
def config(self): # type: () -> Config
def config(self) -> Config:
return self._config
def set_locker(self, locker): # type: (Locker) -> Poetry
def set_locker(self, locker: Locker) -> "Poetry":
self._locker = locker
return self
def set_pool(self, pool): # type: (Pool) -> Poetry
def set_pool(self, pool: Pool) -> "Poetry":
self._pool = pool
return self
def set_config(self, config): # type: (Config) -> Poetry
def set_config(self, config: Config) -> "Poetry":
self._config = config
return self
......@@ -14,10 +14,10 @@ from .uploader import Uploader
if TYPE_CHECKING:
from cleo.io.buffered_io import BufferedIO # noqa
from cleo.io.null_io import NullIO # noqa
from cleo.io import BufferedIO
from cleo.io import ConsoleIO
from ..poetry import Poetry # noqa
from ..poetry import Poetry
logger = logging.getLogger(__name__)
......@@ -27,9 +27,7 @@ class Publisher:
Registers and publishes packages to remote repositories.
"""
def __init__(
self, poetry, io
): # type: ("Poetry", Union["BufferedIO", "NullIO"]) -> None
def __init__(self, poetry: "Poetry", io: Union["BufferedIO", "ConsoleIO"]) -> None:
self._poetry = poetry
self._package = poetry.package
self._io = io
......@@ -37,18 +35,18 @@ class Publisher:
self._password_manager = PasswordManager(poetry.config)
@property
def files(self): # type: () -> List[Path]
def files(self) -> List[Path]:
return self._uploader.files
def publish(
self,
repository_name,
username,
password,
cert=None,
client_cert=None,
dry_run=False,
): # type: (Optional[str], Optional[str], Optional[str], Optional[Path], Optional[Path], Optional[bool]) -> None
repository_name: Optional[str],
username: Optional[str],
password: Optional[str],
cert: Optional[Path] = None,
client_cert: Optional[Path] = None,
dry_run: Optional[bool] = False,
) -> None:
if not repository_name:
url = "https://upload.pypi.org/legacy/"
repository_name = "pypi"
......
......@@ -29,15 +29,15 @@ from poetry.utils.patterns import wheel_file_re
if TYPE_CHECKING:
from cleo.io.null_io import NullIO # noqa
from cleo.io.null_io import NullIO
from poetry.poetry import Poetry # noqa
from poetry.poetry import Poetry
_has_blake2 = hasattr(hashlib, "blake2b")
class UploadError(Exception):
def __init__(self, error): # type: (Union[ConnectionError, HTTPError, str]) -> None
def __init__(self, error: Union[ConnectionError, HTTPError, str]) -> None:
if isinstance(error, HTTPError):
message = "HTTP Error {}: {}".format(
error.response.status_code, error.response.reason
......@@ -53,7 +53,7 @@ class UploadError(Exception):
class Uploader:
def __init__(self, poetry, io): # type: ("Poetry", "NullIO") -> None
def __init__(self, poetry: "Poetry", io: "NullIO") -> None:
self._poetry = poetry
self._package = poetry.package
self._io = io
......@@ -61,11 +61,11 @@ class Uploader:
self._password = None
@property
def user_agent(self): # type: () -> str
def user_agent(self) -> str:
return user_agent("poetry", __version__)
@property
def adapter(self): # type: () -> adapters.HTTPAdapter
def adapter(self) -> adapters.HTTPAdapter:
retry = util.Retry(
connect=5,
total=10,
......@@ -76,7 +76,7 @@ class Uploader:
return adapters.HTTPAdapter(max_retries=retry)
@property
def files(self): # type: () -> List[Path]
def files(self) -> List[Path]:
dist = self._poetry.file.parent / "dist"
version = normalize_version(self._package.version.text)
......@@ -93,11 +93,11 @@ class Uploader:
return sorted(wheels + tars)
def auth(self, username, password): # type: (str, str) -> None
def auth(self, username: str, password: str) -> None:
self._username = username
self._password = password
def make_session(self): # type: () -> requests.Session
def make_session(self) -> requests.Session:
session = requests.session()
if self.is_authenticated():
session.auth = (self._username, self._password)
......@@ -108,12 +108,16 @@ class Uploader:
return session
def is_authenticated(self): # type: () -> bool
def is_authenticated(self) -> bool:
return self._username is not None and self._password is not None
def upload(
self, url, cert=None, client_cert=None, dry_run=False
): # type: (str, Optional[Path], Optional[Path], bool) -> None
self,
url: str,
cert: Optional[Path] = None,
client_cert: Optional[Path] = None,
dry_run: bool = False,
) -> None:
session = self.make_session()
if cert:
......@@ -127,7 +131,7 @@ class Uploader:
finally:
session.close()
def post_data(self, file): # type: (Path) -> Dict[str, Any]
def post_data(self, file: Path) -> Dict[str, Any]:
meta = Metadata.from_package(self._package)
file_type = self._get_type(file)
......@@ -206,8 +210,8 @@ class Uploader:
return data
def _upload(
self, session, url, dry_run=False
): # type: (requests.Session, str, Optional[bool]) -> None
self, session: requests.Session, url: str, dry_run: Optional[bool] = False
) -> None:
try:
self._do_upload(session, url, dry_run)
except HTTPError as e:
......@@ -223,8 +227,8 @@ class Uploader:
raise UploadError(e)
def _do_upload(
self, session, url, dry_run=False
): # type: (requests.Session, str, Optional[bool]) -> None
self, session: requests.Session, url: str, dry_run: Optional[bool] = False
) -> None:
for file in self.files:
# TODO: Check existence
......@@ -234,8 +238,12 @@ class Uploader:
resp.raise_for_status()
def _upload_file(
self, session, url, file, dry_run=False
): # type: (requests.Session, str, Path, Optional[bool]) -> requests.Response
self,
session: requests.Session,
url: str,
file: Path,
dry_run: Optional[bool] = False,
) -> requests.Response:
from cleo.ui.progress_bar import ProgressBar
data = self.post_data(file)
......@@ -305,9 +313,7 @@ class Uploader:
return resp
def _register(
self, session, url
): # type: (requests.Session, str) -> requests.Response
def _register(self, session: requests.Session, url: str) -> requests.Response:
"""
Register a package to a repository.
"""
......@@ -335,7 +341,7 @@ class Uploader:
return resp
def _prepare_data(self, data): # type: (Dict) -> List[Tuple[str, str]]
def _prepare_data(self, data: Dict) -> List[Tuple[str, str]]:
data_to_send = []
for key, value in data.items():
if not isinstance(value, (list, tuple)):
......@@ -346,7 +352,7 @@ class Uploader:
return data_to_send
def _get_type(self, file): # type: (Path) -> str
def _get_type(self, file: Path) -> str:
exts = file.suffixes
if exts[-1] == ".whl":
return "bdist_wheel"
......
......@@ -3,20 +3,20 @@ from typing import Tuple
class SolverProblemError(Exception):
def __init__(self, error): # type: (Exception) -> None
def __init__(self, error: Exception) -> None:
self._error = error
super(SolverProblemError, self).__init__(str(error))
@property
def error(self): # type: () -> Exception
def error(self) -> Exception:
return self._error
class OverrideNeeded(Exception):
def __init__(self, *overrides): # type: (*Dict) -> None
def __init__(self, *overrides: Dict) -> None:
self._overrides = overrides
@property
def overrides(self): # type: () -> Tuple[Dict]
def overrides(self) -> Tuple[Dict]:
return self._overrides
......@@ -46,7 +46,7 @@ logger = logging.getLogger(__name__)
class Indicator(ProgressIndicator):
def _formatter_elapsed(self):
def _formatter_elapsed(self) -> str:
elapsed = time.time() - self._start_time
return "{:.1f}s".format(elapsed)
......@@ -57,8 +57,8 @@ class Provider:
UNSAFE_PACKAGES = {"setuptools", "distribute", "pip", "wheel"}
def __init__(
self, package, pool, io, env=None
): # type: (Package, Pool, Any, Optional[Env]) -> None
self, package: Package, pool: Pool, io: Any, env: Optional[Env] = None
) -> None:
self._package = package
self._pool = pool
self._io = io
......@@ -72,20 +72,20 @@ class Provider:
self._load_deferred = True
@property
def pool(self): # type: () -> Pool
def pool(self) -> Pool:
return self._pool
def is_debugging(self): # type: () -> bool
def is_debugging(self) -> bool:
return self._is_debugging
def set_overrides(self, overrides): # type: (Dict) -> None
def set_overrides(self, overrides: Dict) -> None:
self._overrides = overrides
def load_deferred(self, load_deferred): # type: (bool) -> None
def load_deferred(self, load_deferred: bool) -> None:
self._load_deferred = load_deferred
@contextmanager
def use_environment(self, env): # type: (Env) -> Provider
def use_environment(self, env: Env) -> "Provider":
original_env = self._env
original_python_constraint = self._python_constraint
......@@ -98,8 +98,15 @@ class Provider:
self._python_constraint = original_python_constraint
def search_for(
self, dependency
): # type: (Union[Dependency, VCSDependency, FileDependency, DirectoryDependency, URLDependency]) -> List[DependencyPackage]
self,
dependency: Union[
Dependency,
VCSDependency,
FileDependency,
DirectoryDependency,
URLDependency,
],
) -> List[DependencyPackage]:
"""
Search for the specifications that match the given dependency.
......@@ -154,7 +161,7 @@ class Provider:
return PackageCollection(dependency, packages)
def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package]
def search_for_vcs(self, dependency: VCSDependency) -> List[Package]:
"""
Search for the specifications that match the given VCS dependency.
......@@ -183,8 +190,14 @@ class Provider:
@classmethod
def get_package_from_vcs(
cls, vcs, url, branch=None, tag=None, rev=None, name=None
): # type: (str, str, Optional[str], Optional[str], Optional[str], Optional[str]) -> Package
cls,
vcs: str,
url: str,
branch: Optional[str] = None,
tag: Optional[str] = None,
rev: Optional[str] = None,
name: Optional[str] = None,
) -> Package:
if vcs != "git":
raise ValueError("Unsupported VCS dependency {}".format(vcs))
......@@ -215,7 +228,7 @@ class Provider:
return package
def search_for_file(self, dependency): # type: (FileDependency) -> List[Package]
def search_for_file(self, dependency: FileDependency) -> List[Package]:
if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency]
......@@ -246,7 +259,7 @@ class Provider:
return [package]
@classmethod
def get_package_from_file(cls, file_path): # type: (Path) -> Package
def get_package_from_file(cls, file_path: Path) -> Package:
try:
package = PackageInfo.from_path(path=file_path).to_package(
root_dir=file_path
......@@ -258,9 +271,7 @@ class Provider:
return package
def search_for_directory(
self, dependency
): # type: (DirectoryDependency) -> List[Package]
def search_for_directory(self, dependency: DirectoryDependency) -> List[Package]:
if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency]
......@@ -284,8 +295,8 @@ class Provider:
@classmethod
def get_package_from_directory(
cls, directory, name=None
): # type: (Path, Optional[str]) -> Package
cls, directory: Path, name: Optional[str] = None
) -> Package:
package = PackageInfo.from_directory(path=directory).to_package(
root_dir=directory
)
......@@ -300,7 +311,7 @@ class Provider:
return package
def search_for_url(self, dependency): # type: (URLDependency) -> List[Package]
def search_for_url(self, dependency: URLDependency) -> List[Package]:
if dependency in self._deferred_cache:
return [self._deferred_cache[dependency]]
......@@ -329,7 +340,7 @@ class Provider:
return [package]
@classmethod
def get_package_from_url(cls, url): # type: (str) -> Package
def get_package_from_url(cls, url: str) -> Package:
with temporary_directory() as temp_dir:
temp_dir = Path(temp_dir)
file_name = os.path.basename(urllib.parse.urlparse(url).path)
......@@ -343,8 +354,8 @@ class Provider:
return package
def incompatibilities_for(
self, package
): # type: (DependencyPackage) -> List[Incompatibility]
self, package: DependencyPackage
) -> List[Incompatibility]:
"""
Returns incompatibilities that encapsulate a given package's dependencies,
or that it can't be safely selected.
......@@ -419,9 +430,7 @@ class Provider:
for dep in dependencies
]
def complete_package(
self, package
): # type: (DependencyPackage) -> DependencyPackage
def complete_package(self, package: DependencyPackage) -> DependencyPackage:
if package.is_root():
package = package.clone()
......@@ -695,7 +704,7 @@ class Provider:
return package
def debug(self, message, depth=0): # type: (str, int) -> None
def debug(self, message: str, depth: int = 0) -> None:
if not (self._io.is_very_verbose() or self._io.is_debug()):
return
......@@ -782,7 +791,7 @@ class Provider:
self._io.write(debug_info)
@contextmanager
def progress(self): # type: () -> Iterator[None]
def progress(self) -> Iterator[None]:
if not self._io.output.is_decorated() or self.is_debugging():
self._io.write_line("Resolving dependencies...")
yield
......
......@@ -31,24 +31,24 @@ from .provider import Provider
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import DirectoryDependency # noqa
from poetry.core.packages import FileDependency # noqa
from poetry.core.packages import URLDependency # noqa
from poetry.core.packages import VCSDependency # noqa
from poetry.installation.operations import OperationTypes # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import DirectoryDependency
from poetry.core.packages import FileDependency
from poetry.core.packages import URLDependency
from poetry.core.packages import VCSDependency
from poetry.installation.operations import OperationTypes
class Solver:
def __init__(
self,
package, # type: ProjectPackage
pool, # type: Pool
installed, # type: Repository
locked, # type: Repository
io, # type: IO
remove_untracked=False, # type: bool
provider=None, # type: Optional[Provider]
package: ProjectPackage,
pool: Pool,
installed: Repository,
locked: Repository,
io: IO,
remove_untracked: bool = False,
provider: Optional[Provider] = None,
):
self._package = package
self._pool = pool
......@@ -64,15 +64,15 @@ class Solver:
self._remove_untracked = remove_untracked
@property
def provider(self): # type: () -> Provider
def provider(self) -> Provider:
return self._provider
@contextmanager
def use_environment(self, env): # type: (Env) -> None
def use_environment(self, env: Env) -> None:
with self.provider.use_environment(env):
yield
def solve(self, use_latest=None): # type: (List[str]) -> List["OperationTypes"]
def solve(self, use_latest: List[str] = None) -> List["OperationTypes"]:
with self._provider.progress():
start = time.time()
packages, depths = self._solve(use_latest=use_latest)
......@@ -210,8 +210,8 @@ class Solver:
)
def solve_in_compatibility_mode(
self, overrides, use_latest=None
): # type: (Tuple[Dict], List[str]) -> Tuple[List["Package"], List[int]]
self, overrides: Tuple[Dict], use_latest: List[str] = None
) -> Tuple[List["Package"], List[int]]:
locked = {}
for package in self._locked.packages:
locked[package.name] = DependencyPackage(package.to_dependency(), package)
......@@ -241,9 +241,7 @@ class Solver:
return packages, depths
def _solve(
self, use_latest=None
): # type: (List[str]) -> Tuple[List[Package], List[int]]
def _solve(self, use_latest: List[str] = None) -> Tuple[List[Package], List[int]]:
if self._provider._overrides:
self._overrides.append(self._provider._overrides)
......@@ -296,20 +294,18 @@ class Solver:
class DFSNode(object):
def __init__(
self, id, name, base_name
): # type: (Tuple[str, str, bool], str, str) -> None
def __init__(self, id: Tuple[str, str, bool], name: str, base_name: str) -> None:
self.id = id
self.name = name
self.base_name = base_name
def reachable(self): # type: () -> List
def reachable(self) -> List:
return []
def visit(self, parents): # type: (List[PackageNode]) -> None
def visit(self, parents: List["PackageNode"]) -> None:
pass
def __str__(self): # type: () -> str
def __str__(self) -> str:
return str(self.id)
......@@ -320,8 +316,8 @@ class VisitedState(enum.Enum):
def depth_first_search(
source, aggregator
): # type: (PackageNode, Callable) -> List[Tuple[Package, int]]
source: "PackageNode", aggregator: Callable
) -> List[Tuple[Package, int]]:
back_edges = defaultdict(list)
visited = {}
topo_sorted_nodes = []
......@@ -349,8 +345,11 @@ def depth_first_search(
def dfs_visit(
node, back_edges, visited, sorted_nodes
): # type: (PackageNode, Dict[str, List[PackageNode]], Dict[str, VisitedState], List[PackageNode]) -> bool
node: "PackageNode",
back_edges: Dict[str, List["PackageNode"]],
visited: Dict[str, VisitedState],
sorted_nodes: List["PackageNode"],
) -> bool:
if visited.get(node.id, VisitedState.Unvisited) == VisitedState.Visited:
return True
if visited.get(node.id, VisitedState.Unvisited) == VisitedState.PartiallyVisited:
......@@ -372,12 +371,28 @@ def dfs_visit(
class PackageNode(DFSNode):
def __init__(
self,
package, # type: Package
packages, # type: List[Package]
previous=None, # type: Optional[PackageNode]
previous_dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]]
dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]]
): # type: (...) -> None
package: Package,
packages: List[Package],
previous: Optional["PackageNode"] = None,
previous_dep: Optional[
Union[
"DirectoryDependency",
"FileDependency",
"URLDependency",
"VCSDependency",
"Dependency",
]
] = None,
dep: Optional[
Union[
"DirectoryDependency",
"FileDependency",
"URLDependency",
"VCSDependency",
"Dependency",
]
] = None,
) -> None:
self.package = package
self.packages = packages
......@@ -399,8 +414,8 @@ class PackageNode(DFSNode):
package.name,
)
def reachable(self): # type: () -> List[PackageNode]
children = [] # type: List[PackageNode]
def reachable(self) -> List["PackageNode"]:
children: List[PackageNode] = []
if (
self.previous_dep
......@@ -446,7 +461,7 @@ class PackageNode(DFSNode):
return children
def visit(self, parents): # type: (PackageNode) -> None
def visit(self, parents: "PackageNode") -> None:
# The root package, which has no parents, is defined as having depth -1
# So that the root package's top-level dependencies have depth 0.
self.depth = 1 + max(
......@@ -459,8 +474,8 @@ class PackageNode(DFSNode):
def aggregate_package_nodes(
nodes, children
): # type: (List[PackageNode], List[PackageNode]) -> Tuple[Package, int]
nodes: List[PackageNode], children: List[PackageNode]
) -> Tuple[Package, int]:
package = nodes[0].package
depth = max(node.depth for node in nodes)
category = (
......
......@@ -4,28 +4,28 @@ from typing import Optional
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
class BaseRepository(object):
def __init__(self): # type: () -> None
def __init__(self) -> None:
self._packages = []
@property
def packages(self): # type: () -> List["Package"]
def packages(self) -> List["Package"]:
return self._packages
def has_package(self, package): # type: ("Package") -> None
def has_package(self, package: "Package") -> None:
raise NotImplementedError()
def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> None
self, name: str, version: str, extras: Optional[List[str]] = None
) -> None:
raise NotImplementedError()
def find_packages(self, dependency): # type: ("Dependency") -> None
def find_packages(self, dependency: "Dependency") -> None:
raise NotImplementedError()
def search(self, query): # type: (str) -> None
def search(self, query: str) -> None:
raise NotImplementedError()
......@@ -23,7 +23,7 @@ except NameError:
class InstalledRepository(Repository):
@classmethod
def get_package_paths(cls, env, name): # type: (Env, str) -> Set[Path]
def get_package_paths(cls, env: Env, name: str) -> Set[Path]:
"""
Process a .pth file within the site-packages directories, and return any valid
paths. We skip executable .pth files as there is no reliable means to do this
......@@ -68,9 +68,7 @@ class InstalledRepository(Repository):
return paths
@classmethod
def set_package_vcs_properties_from_path(
cls, src, package
): # type: (Path, Package) -> None
def set_package_vcs_properties_from_path(cls, src: Path, package: Package) -> None:
from poetry.core.vcs.git import Git
git = Git()
......@@ -82,12 +80,12 @@ class InstalledRepository(Repository):
package._source_reference = revision
@classmethod
def set_package_vcs_properties(cls, package, env): # type: (Package, Env) -> None
def set_package_vcs_properties(cls, package: Package, env: Env) -> None:
src = env.path / "src" / package.name
cls.set_package_vcs_properties_from_path(src, package)
@classmethod
def is_vcs_package(cls, package, env): # type: (Union[Path, Package], Env) -> bool
def is_vcs_package(cls, package: Union[Path, Package], env: Env) -> bool:
# A VCS dependency should have been installed
# in the src directory.
src = env.path / "src"
......@@ -102,7 +100,7 @@ class InstalledRepository(Repository):
return True
@classmethod
def load(cls, env): # type: (Env) -> InstalledRepository
def load(cls, env: Env) -> "InstalledRepository":
"""
Load installed packages.
"""
......
......@@ -8,7 +8,7 @@ from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import Generator
from typing import Iterator
from typing import List
from typing import Optional
......@@ -38,7 +38,7 @@ from .pypi_repository import PyPiRepository
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Dependency
try:
from html import unescape
......@@ -75,9 +75,7 @@ class Page:
".tar",
]
def __init__(
self, url, content, headers
): # type: (str, str, Dict[str, Any]) -> None
def __init__(self, url: str, content: str, headers: Dict[str, Any]) -> None:
if not url.endswith("/"):
url += "/"
......@@ -99,7 +97,7 @@ class Page:
)
@property
def versions(self): # type: () -> Generator[Version]
def versions(self) -> Iterator[Version]:
seen = set()
for link in self.links:
version = self.link_version(link)
......@@ -115,7 +113,7 @@ class Page:
yield version
@property
def links(self): # type: () -> Generator[Link]
def links(self) -> Iterator[Link]:
for anchor in self._parsed.findall(".//a"):
if anchor.get("href"):
href = anchor.get("href")
......@@ -130,12 +128,12 @@ class Page:
yield link
def links_for_version(self, version): # type: (Version) -> Generator[Link]
def links_for_version(self, version: Version) -> Iterator[Link]:
for link in self.links:
if self.link_version(link) == version:
yield link
def link_version(self, link): # type: (Link) -> Optional[Version]
def link_version(self, link: Link) -> Optional[Version]:
m = wheel_file_re.match(link.filename)
if m:
version = m.group("ver")
......@@ -156,7 +154,7 @@ class Page:
_clean_re = re.compile(r"[^a-z0-9$&+,/:;=?@.#%_\\|-]", re.I)
def clean_link(self, url): # type: (str) -> str
def clean_link(self, url: str) -> str:
"""Makes sure a link is fully encoded. That is, if a ' ' shows up in
the link, it will be rewritten to %20 (while not over-quoting
% or other characters)."""
......@@ -165,8 +163,14 @@ class Page:
class LegacyRepository(PyPiRepository):
def __init__(
self, name, url, config=None, disable_cache=False, cert=None, client_cert=None
): # type: (str, str, Optional[Config], bool, Optional[Path], Optional[Path]) -> None
self,
name: str,
url: str,
config: Optional[Config] = None,
disable_cache: bool = False,
cert: Optional[Path] = None,
client_cert: Optional[Path] = None,
) -> None:
if name == "pypi":
raise ValueError("The name [pypi] is reserved for repositories")
......@@ -211,15 +215,15 @@ class LegacyRepository(PyPiRepository):
self._disable_cache = disable_cache
@property
def cert(self): # type: () -> Optional[Path]
def cert(self) -> Optional[Path]:
return self._cert
@property
def client_cert(self): # type: () -> Optional[Path]
def client_cert(self) -> Optional[Path]:
return self._client_cert
@property
def authenticated_url(self): # type: () -> str
def authenticated_url(self) -> str:
if not self._session.auth:
return self.url
......@@ -233,7 +237,7 @@ class LegacyRepository(PyPiRepository):
path=parsed.path,
)
def find_packages(self, dependency): # type: ("Dependency") -> List[Package]
def find_packages(self, dependency: "Dependency") -> List[Package]:
packages = []
constraint = dependency.constraint
......@@ -305,8 +309,8 @@ class LegacyRepository(PyPiRepository):
return packages
def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> Package
self, name: str, version: str, extras: Optional[List[str]] = None
) -> Package:
"""
Retrieve the release information.
......@@ -330,14 +334,14 @@ class LegacyRepository(PyPiRepository):
return package
def find_links_for_package(self, package): # type: (Package) -> List[Link]
def find_links_for_package(self, package: Package) -> List[Link]:
page = self._get("/{}/".format(package.name.replace(".", "-")))
if page is None:
return []
return list(page.links_for_version(package.version))
def _get_release_info(self, name, version): # type: (str, str) -> dict
def _get_release_info(self, name: str, version: str) -> dict:
page = self._get("/{}/".format(canonicalize_name(name).replace(".", "-")))
if page is None:
raise PackageNotFound('No package named "{}"'.format(name))
......@@ -385,7 +389,7 @@ class LegacyRepository(PyPiRepository):
return data.asdict()
def _get(self, endpoint): # type: (str) -> Optional[Page]
def _get(self, endpoint: str) -> Optional[Page]:
url = self._url + endpoint
try:
response = self.session.get(url)
......
......@@ -9,19 +9,21 @@ from .repository import Repository
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.core.packages import Dependency
from poetry.core.packages import Package
class Pool(BaseRepository):
def __init__(
self, repositories=None, ignore_repository_names=False
): # type: (Optional[List[Repository]], bool) -> None
self,
repositories: Optional[List[Repository]] = None,
ignore_repository_names: bool = False,
) -> None:
if repositories is None:
repositories = []
self._lookup = {} # type: Dict[str, int]
self._repositories = [] # type: List[Repository]
self._lookup: Dict[str, int] = {}
self._repositories: List[Repository] = []
self._default = False
self._secondary_start_idx = None
......@@ -33,18 +35,18 @@ class Pool(BaseRepository):
super(Pool, self).__init__()
@property
def repositories(self): # type: () -> List[Repository]
def repositories(self) -> List[Repository]:
return self._repositories
def has_default(self): # type: () -> bool
def has_default(self) -> bool:
return self._default
def has_repository(self, name): # type: (str) -> bool
def has_repository(self, name: str) -> bool:
name = name.lower() if name is not None else None
return name in self._lookup
def repository(self, name): # type: (str) -> Repository
def repository(self, name: str) -> Repository:
if name is not None:
name = name.lower()
......@@ -54,8 +56,8 @@ class Pool(BaseRepository):
raise ValueError('Repository "{}" does not exist.'.format(name))
def add_repository(
self, repository, default=False, secondary=False
): # type: (Repository, bool, bool) -> Pool
self, repository: Repository, default: bool = False, secondary: bool = False
) -> "Pool":
"""
Adds a repository to the pool.
"""
......@@ -99,7 +101,7 @@ class Pool(BaseRepository):
return self
def remove_repository(self, repository_name): # type: (str) -> Pool
def remove_repository(self, repository_name: str) -> "Pool":
if repository_name is not None:
repository_name = repository_name.lower()
......@@ -109,12 +111,12 @@ class Pool(BaseRepository):
return self
def has_package(self, package): # type: ("Package") -> bool
def has_package(self, package: "Package") -> bool:
raise NotImplementedError()
def package(
self, name, version, extras=None, repository=None
): # type: (str, str, List[str], str) -> "Package"
self, name: str, version: str, extras: List[str] = None, repository: str = None
) -> "Package":
if repository is not None:
repository = repository.lower()
......@@ -144,7 +146,7 @@ class Pool(BaseRepository):
raise PackageNotFound("Package {} ({}) not found.".format(name, version))
def find_packages(self, dependency): # type: ("Dependency") -> List["Package"]
def find_packages(self, dependency: "Dependency") -> List["Package"]:
repository = dependency.source_name
if repository is not None:
repository = repository.lower()
......@@ -165,7 +167,7 @@ class Pool(BaseRepository):
return packages
def search(self, query): # type: (str) -> List["Package"]
def search(self, query: str) -> List["Package"]:
from .legacy_repository import LegacyRepository
results = []
......
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