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 ...@@ -19,11 +19,11 @@ from .dict_config_source import DictConfigSource
_NOT_SET = object() _NOT_SET = object()
def boolean_validator(val): # type: (str) -> bool def boolean_validator(val: str) -> bool:
return val in {"true", "false", "1", "0"} 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"] return val in ["true", "1"]
...@@ -42,8 +42,8 @@ class Config(object): ...@@ -42,8 +42,8 @@ class Config(object):
} }
def __init__( def __init__(
self, use_environment=True, base_dir=None self, use_environment: bool = True, base_dir: Optional[Path] = None
): # type: (bool, Optional[Path]) -> None ) -> None:
self._config = deepcopy(self.default_config) self._config = deepcopy(self.default_config)
self._use_environment = use_environment self._use_environment = use_environment
self._base_dir = base_dir self._base_dir = base_dir
...@@ -51,38 +51,38 @@ class Config(object): ...@@ -51,38 +51,38 @@ class Config(object):
self._auth_config_source = DictConfigSource() self._auth_config_source = DictConfigSource()
@property @property
def name(self): # type: () -> str def name(self) -> str:
return str(self._file.path) return str(self._file.path)
@property @property
def config(self): # type: () -> Dict def config(self) -> Dict:
return self._config return self._config
@property @property
def config_source(self): # type: () -> ConfigSource def config_source(self) -> ConfigSource:
return self._config_source return self._config_source
@property @property
def auth_config_source(self): # type: () -> ConfigSource def auth_config_source(self) -> ConfigSource:
return self._auth_config_source 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 self._config_source = config_source
return self 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 self._auth_config_source = config_source
return self 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 from poetry.utils.helpers import merge_dicts
merge_dicts(self._config, config) merge_dicts(self._config, config)
def all(self): # type: () -> Dict[str, Any] def all(self) -> Dict[str, Any]:
def _all(config, parent_key=""): # type: (Dict, str) -> Dict def _all(config: Dict, parent_key: str = "") -> Dict:
all_ = {} all_ = {}
for key in config: for key in config:
...@@ -101,10 +101,10 @@ class Config(object): ...@@ -101,10 +101,10 @@ class Config(object):
return _all(self.config) return _all(self.config)
def raw(self): # type: () -> Dict[str, Any] def raw(self) -> Dict[str, Any]:
return self._config 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. Retrieve a setting value.
""" """
...@@ -129,13 +129,13 @@ class Config(object): ...@@ -129,13 +129,13 @@ class Config(object):
return self.process(value) return self.process(value)
def process(self, value): # type: (Any) -> Any def process(self, value: Any) -> Any:
if not isinstance(value, str): if not isinstance(value, str):
return value return value
return re.sub(r"{(.+?)}", lambda m: self.get(m.group(1)), 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 { if name in {
"virtualenvs.create", "virtualenvs.create",
"virtualenvs.in-project", "virtualenvs.in-project",
......
...@@ -2,8 +2,8 @@ from typing import Any ...@@ -2,8 +2,8 @@ from typing import Any
class ConfigSource(object): class ConfigSource(object):
def add_property(self, key, value): # type: (str, Any) -> None def add_property(self, key: str, value: Any) -> None:
raise NotImplementedError() raise NotImplementedError()
def remove_property(self, key): # type: (str) -> None def remove_property(self, key: str) -> None:
raise NotImplementedError() raise NotImplementedError()
...@@ -5,14 +5,14 @@ from .config_source import ConfigSource ...@@ -5,14 +5,14 @@ from .config_source import ConfigSource
class DictConfigSource(ConfigSource): class DictConfigSource(ConfigSource):
def __init__(self): # type: () -> None def __init__(self) -> None:
self._config = {} self._config = {}
@property @property
def config(self): # type: () -> Dict[str, Any] def config(self) -> Dict[str, Any]:
return self._config 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(".") keys = key.split(".")
config = self._config config = self._config
...@@ -26,7 +26,7 @@ class DictConfigSource(ConfigSource): ...@@ -26,7 +26,7 @@ class DictConfigSource(ConfigSource):
config = config[key] config = config[key]
def remove_property(self, key): # type: (str) -> None def remove_property(self, key: str) -> None:
keys = key.split(".") keys = key.split(".")
config = self._config config = self._config
......
from contextlib import contextmanager from contextlib import contextmanager
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any from typing import Any
from typing import Generator from typing import Iterator
from tomlkit import document from tomlkit import document
from tomlkit import table from tomlkit import table
...@@ -10,25 +10,25 @@ from .config_source import ConfigSource ...@@ -10,25 +10,25 @@ from .config_source import ConfigSource
if TYPE_CHECKING: 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): 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._file = file
self._auth_config = auth_config self._auth_config = auth_config
@property @property
def name(self): # type: () -> str def name(self) -> str:
return str(self._file.path) return str(self._file.path)
@property @property
def file(self): # type: () -> "TOMLFile" def file(self) -> "TOMLFile":
return self._file 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: with self.secure() as config:
keys = key.split(".") keys = key.split(".")
...@@ -42,7 +42,7 @@ class FileConfigSource(ConfigSource): ...@@ -42,7 +42,7 @@ class FileConfigSource(ConfigSource):
config = config[key] config = config[key]
def remove_property(self, key): # type: (str) -> None def remove_property(self, key: str) -> None:
with self.secure() as config: with self.secure() as config:
keys = key.split(".") keys = key.split(".")
...@@ -59,7 +59,7 @@ class FileConfigSource(ConfigSource): ...@@ -59,7 +59,7 @@ class FileConfigSource(ConfigSource):
current_config = current_config[key] current_config = current_config[key]
@contextmanager @contextmanager
def secure(self): # type: () -> Generator["TOMLDocument"] def secure(self) -> Iterator["TOMLDocument"]:
if self.file.exists(): if self.file.exists():
initial_config = self.file.read() initial_config = self.file.read()
config = self.file.read() config = self.file.read()
......
...@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING ...@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
from typing import Any from typing import Any
from typing import Callable from typing import Callable
from typing import Optional from typing import Optional
from typing import Type
from typing import cast from typing import cast
from cleo.application import Application as BaseApplication from cleo.application import Application as BaseApplication
...@@ -26,7 +27,7 @@ from .commands.command import Command ...@@ -26,7 +27,7 @@ from .commands.command import Command
def load_command(name: str) -> Callable: def load_command(name: str) -> Callable:
def _load(): def _load() -> Type[Command]:
module = import_module( module = import_module(
"poetry.console.commands.{}".format(".".join(name.split(" "))) "poetry.console.commands.{}".format(".".join(name.split(" ")))
) )
...@@ -75,7 +76,7 @@ COMMANDS = [ ...@@ -75,7 +76,7 @@ COMMANDS = [
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa from poetry.poetry import Poetry
class Application(BaseApplication): class Application(BaseApplication):
...@@ -220,7 +221,7 @@ class Application(BaseApplication): ...@@ -220,7 +221,7 @@ class Application(BaseApplication):
logger.setLevel(level) 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 from .commands.env_command import EnvCommand
command: EnvCommand = cast(EnvCommand, event.command) command: EnvCommand = cast(EnvCommand, event.command)
...@@ -272,7 +273,7 @@ class Application(BaseApplication): ...@@ -272,7 +273,7 @@ class Application(BaseApplication):
command.set_installer(installer) command.set_installer(installer)
def main(): def main() -> int:
return Application().run() return Application().run()
......
...@@ -7,7 +7,7 @@ class AboutCommand(Command): ...@@ -7,7 +7,7 @@ class AboutCommand(Command):
description = "Shows information about Poetry." description = "Shows information about Poetry."
def handle(self): # type: () -> None def handle(self) -> None:
self.line( self.line(
"""<info>Poetry - Package Management for Python</info> """<info>Poetry - Package Management for Python</info>
......
...@@ -68,7 +68,7 @@ class AddCommand(InstallerCommand, InitCommand): ...@@ -68,7 +68,7 @@ class AddCommand(InstallerCommand, InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> int def handle(self) -> int:
from tomlkit import inline_table from tomlkit import inline_table
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
...@@ -192,8 +192,8 @@ class AddCommand(InstallerCommand, InitCommand): ...@@ -192,8 +192,8 @@ class AddCommand(InstallerCommand, InitCommand):
return status return status
def get_existing_packages_from_input( def get_existing_packages_from_input(
self, packages, poetry_content, target_section self, packages: List[str], poetry_content: Dict, target_section: str
): # type: (List[str], Dict, str) -> List[str] ) -> List[str]:
existing_packages = [] existing_packages = []
for name in packages: for name in packages:
...@@ -203,9 +203,7 @@ class AddCommand(InstallerCommand, InitCommand): ...@@ -203,9 +203,7 @@ class AddCommand(InstallerCommand, InitCommand):
return existing_packages return existing_packages
def notify_about_existing_packages( def notify_about_existing_packages(self, existing_packages: List[str]) -> None:
self, existing_packages
): # type: (List[str]) -> None
self.line( self.line(
"The following packages are already present in the pyproject.toml and will be skipped:\n" "The following packages are already present in the pyproject.toml and will be skipped:\n"
) )
......
...@@ -18,7 +18,7 @@ class BuildCommand(EnvCommand): ...@@ -18,7 +18,7 @@ class BuildCommand(EnvCommand):
"poetry.core.masonry.builders.wheel", "poetry.core.masonry.builders.wheel",
] ]
def handle(self): # type: () -> None def handle(self) -> None:
from poetry.core.masonry import Builder from poetry.core.masonry import Builder
fmt = "all" fmt = "all"
......
...@@ -14,7 +14,7 @@ class CacheClearCommand(Command): ...@@ -14,7 +14,7 @@ class CacheClearCommand(Command):
arguments = [argument("cache", description="The name of the cache to clear.")] arguments = [argument("cache", description="The name of the cache to clear.")]
options = [option("all", description="Clear all entries in the cache.")] options = [option("all", description="Clear all entries in the cache.")]
def handle(self): # type: () -> int def handle(self) -> int:
from cachy import CacheManager from cachy import CacheManager
from poetry.locations import REPOSITORY_CACHE_DIR from poetry.locations import REPOSITORY_CACHE_DIR
......
...@@ -10,7 +10,7 @@ class CacheListCommand(Command): ...@@ -10,7 +10,7 @@ class CacheListCommand(Command):
name = "cache list" name = "cache list"
description = "List Poetry's caches." description = "List Poetry's caches."
def handle(self): # type: () -> Optional[int] def handle(self) -> Optional[int]:
from poetry.locations import REPOSITORY_CACHE_DIR from poetry.locations import REPOSITORY_CACHE_DIR
if os.path.exists(str(REPOSITORY_CACHE_DIR)): if os.path.exists(str(REPOSITORY_CACHE_DIR)):
......
...@@ -11,7 +11,7 @@ class CheckCommand(Command): ...@@ -11,7 +11,7 @@ class CheckCommand(Command):
name = "check" name = "check"
description = "Checks the validity of the <comment>pyproject.toml</comment> file." 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 # Load poetry config and display errors, if any
poetry_file = Factory.locate(Path.cwd()) poetry_file = Factory.locate(Path.cwd())
config = PyProjectTOML(poetry_file).poetry_config config = PyProjectTOML(poetry_file).poetry_config
......
...@@ -4,16 +4,19 @@ from cleo.commands.command import Command as BaseCommand ...@@ -4,16 +4,19 @@ from cleo.commands.command import Command as BaseCommand
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa from poetry.console.application import Application
from poetry.poetry import Poetry
class Command(BaseCommand): class Command(BaseCommand):
loggers = [] loggers = []
@property @property
def poetry(self): # type: () -> "Poetry" def poetry(self) -> "Poetry":
return self.application.poetry return self.get_application().poetry
def get_application(self) -> "Application":
return self.application
def reset_poetry(self): # type: () -> None def reset_poetry(self) -> None:
self.application.reset_poetry() self.get_application().reset_poetry()
...@@ -19,7 +19,7 @@ from .command import Command ...@@ -19,7 +19,7 @@ from .command import Command
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.config.config_source import ConfigSource # noqa from poetry.config.config_source import ConfigSource
class ConfigCommand(Command): class ConfigCommand(Command):
...@@ -51,7 +51,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -51,7 +51,7 @@ To remove a repository (repo is a short alias for repositories):
LIST_PROHIBITED_SETTINGS = {"http-basic", "pypi-token"} LIST_PROHIBITED_SETTINGS = {"http-basic", "pypi-token"}
@property @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 pathlib import Path
from poetry.config.config import boolean_normalizer from poetry.config.config import boolean_normalizer
...@@ -90,7 +90,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -90,7 +90,7 @@ To remove a repository (repo is a short alias for repositories):
return unique_config_values return unique_config_values
def handle(self): # type: () -> Optional[int] def handle(self) -> Optional[int]:
from pathlib import Path from pathlib import Path
from poetry.config.file_config_source import FileConfigSource from poetry.config.file_config_source import FileConfigSource
...@@ -269,8 +269,12 @@ To remove a repository (repo is a short alias for repositories): ...@@ -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"))) raise ValueError("Setting {} does not exist".format(self.argument("key")))
def _handle_single_value( def _handle_single_value(
self, source, key, callbacks, values self,
): # type: ("ConfigSource", str, Tuple[Any, Any, Any], List[Any]) -> int source: "ConfigSource",
key: str,
callbacks: Tuple[Any, Any, Any],
values: List[Any],
) -> int:
validator, normalizer, _ = callbacks validator, normalizer, _ = callbacks
if len(values) > 1: if len(values) > 1:
...@@ -284,7 +288,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -284,7 +288,7 @@ To remove a repository (repo is a short alias for repositories):
return 0 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 orig_k = k
for key, value in sorted(config.items()): for key, value in sorted(config.items()):
if k + key in self.LIST_PROHIBITED_SETTINGS: if k + key in self.LIST_PROHIBITED_SETTINGS:
...@@ -319,8 +323,12 @@ To remove a repository (repo is a short alias for repositories): ...@@ -319,8 +323,12 @@ To remove a repository (repo is a short alias for repositories):
self.line(message) self.line(message)
def _get_setting( def _get_setting(
self, contents, setting=None, k=None, default=None self,
): # type: (Dict, Optional[str], Optional[str], Optional[Any]) -> List[Tuple[str, str]] contents: Dict,
setting: Optional[str] = None,
k: Optional[str] = None,
default: Optional[Any] = None,
) -> List[Tuple[str, str]]:
orig_k = k orig_k = k
if setting and setting.split(".")[0] not in contents: if setting and setting.split(".")[0] not in contents:
......
...@@ -8,7 +8,7 @@ class DebugInfoCommand(Command): ...@@ -8,7 +8,7 @@ class DebugInfoCommand(Command):
name = "debug info" name = "debug info"
description = "Shows debug information." 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]) poetry_python_version = ".".join(str(s) for s in sys.version_info[:3])
self.line("") self.line("")
......
from typing import TYPE_CHECKING
from typing import Optional from typing import Optional
from cleo.helpers import argument from cleo.helpers import argument
...@@ -7,6 +8,10 @@ from cleo.io.outputs.output import Verbosity ...@@ -7,6 +8,10 @@ from cleo.io.outputs.output import Verbosity
from ..init import InitCommand from ..init import InitCommand
if TYPE_CHECKING:
from poetry.console.commands.show import ShowCommand
class DebugResolveCommand(InitCommand): class DebugResolveCommand(InitCommand):
name = "debug resolve" name = "debug resolve"
...@@ -30,7 +35,7 @@ class DebugResolveCommand(InitCommand): ...@@ -30,7 +35,7 @@ class DebugResolveCommand(InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] 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 cleo.io.null_io import NullIO
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
...@@ -88,7 +93,7 @@ class DebugResolveCommand(InitCommand): ...@@ -88,7 +93,7 @@ class DebugResolveCommand(InitCommand):
self.line("") self.line("")
if self.option("tree"): if self.option("tree"):
show_command = self.application.find("show") show_command: ShowCommand = self.application.find("show")
show_command.init_styles(self.io) show_command.init_styles(self.io)
packages = [op.package for op in ops] packages = [op.package for op in ops]
......
...@@ -7,7 +7,7 @@ from ..command import Command ...@@ -7,7 +7,7 @@ from ..command import Command
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.utils.env import Env # noqa from poetry.utils.env import Env
class EnvInfoCommand(Command): class EnvInfoCommand(Command):
...@@ -17,7 +17,7 @@ class EnvInfoCommand(Command): ...@@ -17,7 +17,7 @@ class EnvInfoCommand(Command):
options = [option("path", "p", "Only display the environment's path.")] 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 from poetry.utils.env import EnvManager
env = EnvManager(self.poetry).get() env = EnvManager(self.poetry).get()
...@@ -32,7 +32,7 @@ class EnvInfoCommand(Command): ...@@ -32,7 +32,7 @@ class EnvInfoCommand(Command):
self._display_complete_info(env) 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]) env_python_version = ".".join(str(s) for s in env.version_info[:3])
self.line("") self.line("")
self.line("<b>Virtualenv</b>") self.line("<b>Virtualenv</b>")
......
...@@ -10,7 +10,7 @@ class EnvListCommand(Command): ...@@ -10,7 +10,7 @@ class EnvListCommand(Command):
options = [option("full-path", None, "Output the full paths of the virtualenvs.")] 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 from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry) manager = EnvManager(self.poetry)
......
...@@ -12,7 +12,7 @@ class EnvRemoveCommand(Command): ...@@ -12,7 +12,7 @@ class EnvRemoveCommand(Command):
argument("python", "The python executable to remove the virtualenv for.") 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 from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry) manager = EnvManager(self.poetry)
......
...@@ -10,7 +10,7 @@ class EnvUseCommand(Command): ...@@ -10,7 +10,7 @@ class EnvUseCommand(Command):
arguments = [argument("python", "The python executable to use.")] arguments = [argument("python", "The python executable to use.")]
def handle(self): # type: () -> None def handle(self) -> None:
from poetry.utils.env import EnvManager from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry) manager = EnvManager(self.poetry)
......
...@@ -4,18 +4,18 @@ from .command import Command ...@@ -4,18 +4,18 @@ from .command import Command
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.utils.env import VirtualEnv # noqa from poetry.utils.env import VirtualEnv
class EnvCommand(Command): class EnvCommand(Command):
def __init__(self): # type: () -> None def __init__(self) -> None:
self._env = None self._env = None
super(EnvCommand, self).__init__() super(EnvCommand, self).__init__()
@property @property
def env(self): # type: () -> "VirtualEnv" def env(self) -> "VirtualEnv":
return self._env return self._env
def set_env(self, env): # type: ("VirtualEnv") -> None def set_env(self, env: "VirtualEnv") -> None:
self._env = env self._env = env
...@@ -31,7 +31,7 @@ class ExportCommand(Command): ...@@ -31,7 +31,7 @@ class ExportCommand(Command):
option("with-credentials", None, "Include credentials for extra indices."), option("with-credentials", None, "Include credentials for extra indices."),
] ]
def handle(self): # type: () -> None def handle(self) -> None:
fmt = self.option("format") fmt = self.option("format")
if fmt not in Exporter.ACCEPTED_FORMATS: if fmt not in Exporter.ACCEPTED_FORMATS:
......
...@@ -7,6 +7,7 @@ import sys ...@@ -7,6 +7,7 @@ import sys
import urllib.parse import urllib.parse
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional from typing import Optional
...@@ -23,6 +24,10 @@ from .command import Command ...@@ -23,6 +24,10 @@ from .command import Command
from .env_command import EnvCommand from .env_command import EnvCommand
if TYPE_CHECKING:
from poetry.repositories import Pool
class InitCommand(Command): class InitCommand(Command):
name = "init" name = "init"
description = ( description = (
...@@ -57,12 +62,12 @@ class InitCommand(Command): ...@@ -57,12 +62,12 @@ class InitCommand(Command):
The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the current directory. 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__() super(InitCommand, self).__init__()
self._pool = None self._pool = None
def handle(self): # type: () -> int def handle(self) -> int:
from pathlib import Path from pathlib import Path
from poetry.core.vcs.git import GitConfig 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 ...@@ -227,8 +232,11 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
f.write(content) f.write(content)
def _determine_requirements( def _determine_requirements(
self, requires, allow_prereleases=False, source=None self,
): # type: (List[str], bool, Optional[str]) -> List[Dict[str, Union[str, List[str]]]] requires: List[str],
allow_prereleases: bool = False,
source: Optional[str] = None,
) -> List[Dict[str, Union[str, List[str]]]]:
if not requires: if not requires:
requires = [] requires = []
...@@ -354,8 +362,12 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -354,8 +362,12 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return result return result
def _find_best_version_for_package( def _find_best_version_for_package(
self, name, required_version=None, allow_prereleases=False, source=None self,
): # type: (str, Optional[str], bool, Optional[str]) -> Tuple[str, str] 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 from poetry.version.version_selector import VersionSelector
selector = VersionSelector(self._get_pool()) selector = VersionSelector(self._get_pool())
...@@ -371,9 +383,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -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) return package.pretty_name, selector.find_recommended_require_version(package)
def _parse_requirements( def _parse_requirements(self, requirements: List[str]) -> List[Dict[str, str]]:
self, requirements
): # type: (List[str]) -> List[Dict[str, str]]
from poetry.puzzle.provider import Provider from poetry.puzzle.provider import Provider
result = [] result = []
...@@ -490,8 +500,8 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -490,8 +500,8 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return result return result
def _format_requirements( def _format_requirements(
self, requirements self, requirements: List[Dict[str, str]]
): # type: (List[Dict[str, str]]) -> Dict[str, Union[str, Dict[str, str]]] ) -> Dict[str, Union[str, Dict[str, str]]]:
requires = {} requires = {}
for requirement in requirements: for requirement in requirements:
name = requirement.pop("name") name = requirement.pop("name")
...@@ -506,7 +516,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -506,7 +516,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return requires 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 from poetry.core.packages.package import AUTHOR_REGEX
author = author or default author = author or default
...@@ -523,7 +533,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -523,7 +533,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return author 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 from poetry.core.spdx import license_by_id
if license: if license:
...@@ -531,7 +541,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -531,7 +541,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return license return license
def _get_pool(self): # type: () -> "Pool" def _get_pool(self) -> "Pool":
from poetry.repositories import Pool from poetry.repositories import Pool
from poetry.repositories.pypi_repository import PyPiRepository from poetry.repositories.pypi_repository import PyPiRepository
......
...@@ -50,7 +50,7 @@ dependencies and not including the current project, run the command with the ...@@ -50,7 +50,7 @@ dependencies and not including the current project, run the command with the
_loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] _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.core.masonry.utils.module import ModuleOrPackageNotFound
from poetry.masonry.builders import EditableBuilder from poetry.masonry.builders import EditableBuilder
......
...@@ -9,20 +9,20 @@ if TYPE_CHECKING: ...@@ -9,20 +9,20 @@ if TYPE_CHECKING:
class InstallerCommand(EnvCommand): class InstallerCommand(EnvCommand):
def __init__(self): # type: () -> None def __init__(self) -> None:
self._installer = None # type: Optional[Installer] self._installer: Optional["Installer"] = None
super(InstallerCommand, self).__init__() super(InstallerCommand, self).__init__()
def reset_poetry(self): # type: () -> None def reset_poetry(self) -> None:
super(InstallerCommand, self).reset_poetry() super(InstallerCommand, self).reset_poetry()
self._installer.set_package(self.poetry.package) self._installer.set_package(self.poetry.package)
self._installer.set_locker(self.poetry.locker) self._installer.set_locker(self.poetry.locker)
@property @property
def installer(self): # type: () -> Installer def installer(self) -> "Installer":
return self._installer return self._installer
def set_installer(self, installer): # type: (Installer) -> None def set_installer(self, installer: "Installer") -> None:
self._installer = installer self._installer = installer
...@@ -24,7 +24,7 @@ file. ...@@ -24,7 +24,7 @@ file.
loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): # type: () -> int def handle(self) -> int:
self._installer.use_executor( self._installer.use_executor(
self.poetry.config.get("experimental.new-installer", False) self.poetry.config.get("experimental.new-installer", False)
) )
......
...@@ -19,7 +19,7 @@ class NewCommand(Command): ...@@ -19,7 +19,7 @@ class NewCommand(Command):
option("src", None, "Use the src layout for the project."), option("src", None, "Use the src layout for the project."),
] ]
def handle(self): # type: () -> None def handle(self) -> None:
from pathlib import Path from pathlib import Path
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
......
...@@ -41,7 +41,7 @@ the config command. ...@@ -41,7 +41,7 @@ the config command.
loggers = ["poetry.masonry.publishing.publisher"] loggers = ["poetry.masonry.publishing.publisher"]
def handle(self): # type: () -> Optional[int] def handle(self) -> Optional[int]:
from poetry.publishing.publisher import Publisher from poetry.publishing.publisher import Publisher
publisher = Publisher(self.poetry, self.io) publisher = Publisher(self.poetry, self.io)
......
...@@ -27,7 +27,7 @@ list of installed packages ...@@ -27,7 +27,7 @@ list of installed packages
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> int def handle(self) -> int:
packages = self.argument("packages") packages = self.argument("packages")
is_dev = self.option("dev") is_dev = self.option("dev")
......
from typing import TYPE_CHECKING
from typing import Any from typing import Any
from typing import Union from typing import Union
...@@ -6,6 +7,10 @@ from cleo.helpers import argument ...@@ -6,6 +7,10 @@ from cleo.helpers import argument
from .env_command import EnvCommand from .env_command import EnvCommand
if TYPE_CHECKING:
from poetry.core.masonry.utils.module import Module
class RunCommand(EnvCommand): class RunCommand(EnvCommand):
name = "run" name = "run"
...@@ -15,7 +20,7 @@ class RunCommand(EnvCommand): ...@@ -15,7 +20,7 @@ class RunCommand(EnvCommand):
argument("args", "The command and arguments/options to run.", multiple=True) argument("args", "The command and arguments/options to run.", multiple=True)
] ]
def handle(self): # type: () -> Any def handle(self) -> Any:
args = self.argument("args") args = self.argument("args")
script = args[0] script = args[0]
scripts = self.poetry.local_config.get("scripts") scripts = self.poetry.local_config.get("scripts")
...@@ -26,7 +31,7 @@ class RunCommand(EnvCommand): ...@@ -26,7 +31,7 @@ class RunCommand(EnvCommand):
return self.env.execute(*args) return self.env.execute(*args)
@property @property
def _module(self): def _module(self) -> "Module":
from poetry.core.masonry.utils.module import Module from poetry.core.masonry.utils.module import Module
poetry = self.poetry poetry = self.poetry
...@@ -36,7 +41,7 @@ class RunCommand(EnvCommand): ...@@ -36,7 +41,7 @@ class RunCommand(EnvCommand):
return module 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): if isinstance(script, dict):
script = script["callable"] script = script["callable"]
......
...@@ -10,7 +10,7 @@ class SearchCommand(Command): ...@@ -10,7 +10,7 @@ class SearchCommand(Command):
arguments = [argument("tokens", "The tokens to search for.", multiple=True)] 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 from poetry.repositories.pypi_repository import PyPiRepository
results = PyPiRepository().search(self.argument("tokens")) results = PyPiRepository().search(self.argument("tokens"))
......
...@@ -11,6 +11,7 @@ import tarfile ...@@ -11,6 +11,7 @@ import tarfile
from functools import cmp_to_key from functools import cmp_to_key
from gzip import GzipFile from gzip import GzipFile
from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any from typing import Any
...@@ -24,9 +25,8 @@ from ..command import Command ...@@ -24,9 +25,8 @@ from ..command import Command
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
from poetry.core.semver import Version from poetry.core.semver import Version
from poetry.utils._compat import Path
try: try:
...@@ -70,24 +70,24 @@ class SelfUpdateCommand(Command): ...@@ -70,24 +70,24 @@ class SelfUpdateCommand(Command):
BASE_URL = REPOSITORY_URL + "/releases/download" BASE_URL = REPOSITORY_URL + "/releases/download"
@property @property
def home(self): # type: () -> Path def home(self) -> Path:
from pathlib import Path from pathlib import Path
return Path(os.environ.get("POETRY_HOME", "~/.poetry")).expanduser() return Path(os.environ.get("POETRY_HOME", "~/.poetry")).expanduser()
@property @property
def bin(self): # type: () -> Path def bin(self) -> Path:
return self.home / "bin" return self.home / "bin"
@property @property
def lib(self): # type: () -> Path def lib(self) -> Path:
return self.home / "lib" return self.home / "lib"
@property @property
def lib_backup(self): # type: () -> Path def lib_backup(self) -> Path:
return self.home / "lib-backup" return self.home / "lib-backup"
def handle(self): # type: () -> None def handle(self) -> None:
from poetry.__version__ import __version__ from poetry.__version__ import __version__
from poetry.core.semver import Version from poetry.core.semver import Version
from poetry.repositories.pypi_repository import PyPiRepository from poetry.repositories.pypi_repository import PyPiRepository
...@@ -138,7 +138,7 @@ class SelfUpdateCommand(Command): ...@@ -138,7 +138,7 @@ class SelfUpdateCommand(Command):
self.update(release) self.update(release)
def update(self, release): # type: ("Package") -> None def update(self, release: "Package") -> None:
version = release.version version = release.version
self.line("Updating to <info>{}</info>".format(version)) self.line("Updating to <info>{}</info>".format(version))
...@@ -174,7 +174,7 @@ class SelfUpdateCommand(Command): ...@@ -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 from poetry.utils.helpers import temporary_directory
release_name = self._get_release_name(version) release_name = self._get_release_name(version)
...@@ -244,10 +244,10 @@ class SelfUpdateCommand(Command): ...@@ -244,10 +244,10 @@ class SelfUpdateCommand(Command):
finally: finally:
gz.close() gz.close()
def process(self, *args): # type: (*Any) -> str def process(self, *args: Any) -> str:
return subprocess.check_output(list(args), stderr=subprocess.STDOUT) 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 from pathlib import Path
current = Path(__file__) current = Path(__file__)
...@@ -259,14 +259,14 @@ class SelfUpdateCommand(Command): ...@@ -259,14 +259,14 @@ class SelfUpdateCommand(Command):
"so it cannot be updated automatically." "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 platform = sys.platform
if platform == "linux2": if platform == "linux2":
platform = "linux" platform = "linux"
return "poetry-{}-{}".format(version, platform) return "poetry-{}-{}".format(version, platform)
def make_bin(self): # type: () -> None def make_bin(self) -> None:
from poetry.utils._compat import WINDOWS from poetry.utils._compat import WINDOWS
self.bin.mkdir(0o755, parents=True, exist_ok=True) self.bin.mkdir(0o755, parents=True, exist_ok=True)
...@@ -295,7 +295,7 @@ class SelfUpdateCommand(Command): ...@@ -295,7 +295,7 @@ class SelfUpdateCommand(Command):
st = os.stat(str(self.bin.joinpath("poetry"))) st = os.stat(str(self.bin.joinpath("poetry")))
os.chmod(str(self.bin.joinpath("poetry")), st.st_mode | stat.S_IEXEC) 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. Decides which python executable we'll embed in the launcher script.
""" """
......
...@@ -16,7 +16,7 @@ class ShellCommand(EnvCommand): ...@@ -16,7 +16,7 @@ class ShellCommand(EnvCommand):
If one doesn't exist yet, it will be created. 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 from poetry.utils.shell import Shell
# Check if it's already activated or doesn't exist and won't be created # Check if it's already activated or doesn't exist and won't be created
......
...@@ -13,8 +13,8 @@ from .env_command import EnvCommand ...@@ -13,8 +13,8 @@ from .env_command import EnvCommand
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.io.io import IO # noqa from cleo.io.io import IO # noqa
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
from poetry.repositories import Repository from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.installed_repository import InstalledRepository
...@@ -46,7 +46,7 @@ lists all packages available.""" ...@@ -46,7 +46,7 @@ lists all packages available."""
colors = ["cyan", "yellow", "green", "magenta", "blue"] 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.io.null_io import NullIO
from cleo.terminal import Terminal from cleo.terminal import Terminal
...@@ -271,8 +271,8 @@ lists all packages available.""" ...@@ -271,8 +271,8 @@ lists all packages available."""
self.line(line) self.line(line)
def display_package_tree( def display_package_tree(
self, io, package, installed_repo self, io: "IO", package: "Package", installed_repo: "Repository"
): # type: ("IO", "Package", "Repository") -> None ) -> None:
io.write("<c1>{}</c1>".format(package.pretty_name)) io.write("<c1>{}</c1>".format(package.pretty_name))
description = "" description = ""
if package.description: if package.description:
...@@ -309,13 +309,13 @@ lists all packages available.""" ...@@ -309,13 +309,13 @@ lists all packages available."""
def _display_tree( def _display_tree(
self, self,
io, # type: "IO" io: "IO",
dependency, # type: "Dependency" dependency: "Dependency",
installed_repo, # type: "Repository" installed_repo: "Repository",
packages_in_tree, # type: List[str] packages_in_tree: List[str],
previous_tree_bar="├", # type: str previous_tree_bar: str = "├",
level=1, # type: int level: int = 1,
): # type: (...) -> None ) -> None:
previous_tree_bar = previous_tree_bar.replace("├", "│") previous_tree_bar = previous_tree_bar.replace("├", "│")
dependencies = [] dependencies = []
...@@ -360,7 +360,7 @@ lists all packages available.""" ...@@ -360,7 +360,7 @@ lists all packages available."""
io, dependency, installed_repo, current_tree, tree_bar, level + 1 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(): if not io.output.supports_utf8():
line = line.replace("└", "`-") line = line.replace("└", "`-")
line = line.replace("├", "|-") line = line.replace("├", "|-")
...@@ -369,7 +369,7 @@ lists all packages available.""" ...@@ -369,7 +369,7 @@ lists all packages available."""
io.write_line(line) 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 from cleo.formatters.style import Style
for color in self.colors: for color in self.colors:
...@@ -378,8 +378,8 @@ lists all packages available.""" ...@@ -378,8 +378,8 @@ lists all packages available."""
io.error_output.formatter.set_style(color, style) io.error_output.formatter.set_style(color, style)
def find_latest_package( def find_latest_package(
self, package, include_dev self, package: "Package", include_dev: bool
): # type: ("Package", bool) -> Union["Package", bool] ) -> Union["Package", bool]:
from cleo.io.null_io import NullIO from cleo.io.null_io import NullIO
from poetry.puzzle.provider import Provider from poetry.puzzle.provider import Provider
...@@ -407,7 +407,7 @@ lists all packages available.""" ...@@ -407,7 +407,7 @@ lists all packages available."""
return selector.find_best_candidate(name, ">={}".format(package.pretty_version)) 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 from poetry.core.semver import parse_constraint
if latest.full_pretty_version == package.full_pretty_version: if latest.full_pretty_version == package.full_pretty_version:
...@@ -423,8 +423,8 @@ lists all packages available.""" ...@@ -423,8 +423,8 @@ lists all packages available."""
return "update-possible" return "update-possible"
def get_installed_status( def get_installed_status(
self, locked, installed_repo self, locked: "Package", installed_repo: "InstalledRepository"
): # type: ("Package", "InstalledRepository") -> str ) -> str:
for package in installed_repo.packages: for package in installed_repo.packages:
if locked.name == package.name: if locked.name == package.name:
return "installed" return "installed"
......
...@@ -27,7 +27,7 @@ class UpdateCommand(InstallerCommand): ...@@ -27,7 +27,7 @@ class UpdateCommand(InstallerCommand):
loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): # type: () -> int def handle(self) -> int:
packages = self.argument("packages") packages = self.argument("packages")
self._installer.use_executor( self._installer.use_executor(
......
from typing import TYPE_CHECKING
from cleo.helpers import argument from cleo.helpers import argument
from cleo.helpers import option from cleo.helpers import option
from .command import Command from .command import Command
if TYPE_CHECKING:
from poetry.core.semver import Version
class VersionCommand(Command): class VersionCommand(Command):
name = "version" name = "version"
...@@ -40,7 +46,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease. ...@@ -40,7 +46,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease.
"prerelease", "prerelease",
} }
def handle(self): # type: () -> None def handle(self) -> None:
version = self.argument("version") version = self.argument("version")
if version: if version:
...@@ -72,7 +78,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease. ...@@ -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 from poetry.core.semver import Version
try: try:
......
...@@ -4,7 +4,7 @@ from .formatter import Formatter ...@@ -4,7 +4,7 @@ from .formatter import Formatter
class BuilderLogFormatter(Formatter): class BuilderLogFormatter(Formatter):
def format(self, msg): # type: (str) -> str def format(self, msg: str) -> str:
if msg.startswith("Building "): if msg.startswith("Building "):
msg = re.sub("Building (.+)", " - Building <info>\\1</info>", msg) msg = re.sub("Building (.+)", " - Building <info>\\1</info>", msg)
elif msg.startswith("Built "): elif msg.startswith("Built "):
......
...@@ -2,5 +2,5 @@ import logging ...@@ -2,5 +2,5 @@ import logging
class Formatter(object): class Formatter(object):
def format(self, record): # type: (logging.LogRecord) -> str def format(self, record: logging.LogRecord) -> str:
raise NotImplementedError() raise NotImplementedError()
...@@ -6,7 +6,7 @@ from .formatters import FORMATTERS ...@@ -6,7 +6,7 @@ from .formatters import FORMATTERS
if TYPE_CHECKING: if TYPE_CHECKING:
from logging import LogRecord # noqa from logging import LogRecord
class IOFormatter(logging.Formatter): class IOFormatter(logging.Formatter):
...@@ -18,7 +18,7 @@ class IOFormatter(logging.Formatter): ...@@ -18,7 +18,7 @@ class IOFormatter(logging.Formatter):
"info": "fg=blue", "info": "fg=blue",
} }
def format(self, record): # type: ("LogRecord") -> str def format(self, record: "LogRecord") -> str:
if not record.exc_info: if not record.exc_info:
level = record.levelname.lower() level = record.levelname.lower()
msg = record.msg msg = record.msg
......
...@@ -4,18 +4,18 @@ from typing import TYPE_CHECKING ...@@ -4,18 +4,18 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from logging import LogRecord # noqa from logging import LogRecord
from cleo.io.io import IO # noqa from cleo.io.io import IO # noqa
class IOHandler(logging.Handler): class IOHandler(logging.Handler):
def __init__(self, io): # type: ("IO") -> None def __init__(self, io: "IO") -> None:
self._io = io self._io = io
super(IOHandler, self).__init__() super(IOHandler, self).__init__()
def emit(self, record): # type: ("LogRecord") -> None def emit(self, record: "LogRecord") -> None:
try: try:
msg = self.format(record) msg = self.format(record)
level = record.levelname.lower() level = record.levelname.lower()
......
...@@ -2,6 +2,7 @@ from __future__ import absolute_import ...@@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import unicode_literals from __future__ import unicode_literals
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import Optional from typing import Optional
...@@ -19,14 +20,18 @@ from .poetry import Poetry ...@@ -19,14 +20,18 @@ from .poetry import Poetry
from .repositories.pypi_repository import PyPiRepository from .repositories.pypi_repository import PyPiRepository
if TYPE_CHECKING:
from .repositories.legacy_repository import LegacyRepository
class Factory(BaseFactory): class Factory(BaseFactory):
""" """
Factory class to create various elements needed by Poetry. Factory class to create various elements needed by Poetry.
""" """
def create_poetry( def create_poetry(
self, cwd=None, io=None self, cwd: Optional[Path] = None, io: Optional[IO] = None
): # type: (Optional[Path], Optional[IO]) -> Poetry ) -> Poetry:
if io is None: if io is None:
io = NullIO() io = NullIO()
...@@ -100,7 +105,7 @@ class Factory(BaseFactory): ...@@ -100,7 +105,7 @@ class Factory(BaseFactory):
return poetry return poetry
@classmethod @classmethod
def create_config(cls, io=None): # type: (Optional[IO]) -> Config def create_config(cls, io: Optional[IO] = None) -> Config:
if io is None: if io is None:
io = NullIO() io = NullIO()
...@@ -136,8 +141,8 @@ class Factory(BaseFactory): ...@@ -136,8 +141,8 @@ class Factory(BaseFactory):
return config return config
def create_legacy_repository( def create_legacy_repository(
self, source, auth_config self, source: Dict[str, str], auth_config: Config
): # type: (Dict[str, str], Config) -> "LegacyRepository" ) -> "LegacyRepository":
from .repositories.legacy_repository import LegacyRepository from .repositories.legacy_repository import LegacyRepository
from .utils.helpers import get_cert from .utils.helpers import get_cert
from .utils.helpers import get_client_cert from .utils.helpers import get_client_cert
......
...@@ -43,8 +43,8 @@ PEP517_META_BUILD_DEPS = ["pep517===0.8.2", "toml==0.10.1"] ...@@ -43,8 +43,8 @@ PEP517_META_BUILD_DEPS = ["pep517===0.8.2", "toml==0.10.1"]
class PackageInfoError(ValueError): class PackageInfoError(ValueError):
def __init__( def __init__(
self, path, *reasons self, path: Union[Path, str], *reasons: Union[BaseException, str]
): # type: (Union[Path, str], *Union[BaseException, str]) -> None ) -> None:
reasons = ( reasons = (
"Unable to determine package info for path: {}".format(str(path)), "Unable to determine package info for path: {}".format(str(path)),
) + reasons ) + reasons
...@@ -56,14 +56,14 @@ class PackageInfoError(ValueError): ...@@ -56,14 +56,14 @@ class PackageInfoError(ValueError):
class PackageInfo: class PackageInfo:
def __init__( def __init__(
self, self,
name=None, # type: Optional[str] name: Optional[str] = None,
version=None, # type: Optional[str] version: Optional[str] = None,
summary=None, # type: Optional[str] summary: Optional[str] = None,
platform=None, # type: Optional[str] platform: Optional[str] = None,
requires_dist=None, # type: Optional[List[str]] requires_dist: Optional[List[str]] = None,
requires_python=None, # type: Optional[str] requires_python: Optional[str] = None,
files=None, # type: Optional[List[str]] files: Optional[List[str]] = None,
cache_version=None, # type: Optional[str] cache_version: Optional[str] = None,
): ):
self.name = name self.name = name
self.version = version self.version = version
...@@ -78,10 +78,10 @@ class PackageInfo: ...@@ -78,10 +78,10 @@ class PackageInfo:
self._source_reference = None self._source_reference = None
@property @property
def cache_version(self): # type: () -> Optional[str] def cache_version(self) -> Optional[str]:
return self._cache_version 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.name = other.name or self.name
self.version = other.version or self.version self.version = other.version or self.version
self.summary = other.summary or self.summary self.summary = other.summary or self.summary
...@@ -92,7 +92,7 @@ class PackageInfo: ...@@ -92,7 +92,7 @@ class PackageInfo:
self._cache_version = other.cache_version or self._cache_version self._cache_version = other.cache_version or self._cache_version
return self 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. Helper method to convert package info into a dictionary used for caching.
""" """
...@@ -108,9 +108,7 @@ class PackageInfo: ...@@ -108,9 +108,7 @@ class PackageInfo:
} }
@classmethod @classmethod
def load( def load(cls, data: Dict[str, Optional[Union[str, List[str]]]]) -> "PackageInfo":
cls, data
): # type: (Dict[str, Optional[Union[str, List[str]]]]) -> PackageInfo
""" """
Helper method to load data from a dictionary produced by `PackageInfo.asdict()`. Helper method to load data from a dictionary produced by `PackageInfo.asdict()`.
...@@ -120,13 +118,16 @@ class PackageInfo: ...@@ -120,13 +118,16 @@ class PackageInfo:
return cls(cache_version=cache_version, **data) return cls(cache_version=cache_version, **data)
@classmethod @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.""" """Internal helper method to log information."""
getattr(logger, level)("<debug>{}:</debug> {}".format(cls.__name__, msg)) getattr(logger, level)("<debug>{}:</debug> {}".format(cls.__name__, msg))
def to_package( def to_package(
self, name=None, extras=None, root_dir=None self,
): # type: (Optional[str], Optional[List[str]], Optional[Path]) -> Package 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. Create a new `poetry.core.packages.package.Package` instance using metadata from this instance.
...@@ -202,8 +203,8 @@ class PackageInfo: ...@@ -202,8 +203,8 @@ class PackageInfo:
@classmethod @classmethod
def _from_distribution( def _from_distribution(
cls, dist cls, dist: Union[pkginfo.BDist, pkginfo.SDist, pkginfo.Wheel]
): # type: (Union[pkginfo.BDist, pkginfo.SDist, pkginfo.Wheel]) -> PackageInfo ) -> "PackageInfo":
""" """
Helper method to parse package information from a `pkginfo.Distribution` instance. Helper method to parse package information from a `pkginfo.Distribution` instance.
...@@ -234,7 +235,7 @@ class PackageInfo: ...@@ -234,7 +235,7 @@ class PackageInfo:
return info return info
@classmethod @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 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 file using `pkginfo.SDist`. If this does not provide us with package requirements, we extract the
...@@ -295,11 +296,11 @@ class PackageInfo: ...@@ -295,11 +296,11 @@ class PackageInfo:
return info.update(new_info) return info.update(new_info)
@staticmethod @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) return any((path / f).exists() for f in SetupReader.FILES)
@classmethod @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 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 at `poetry.utils.setup_reader.SetupReader` in order to parse the file. This is not reliable for
...@@ -356,7 +357,7 @@ class PackageInfo: ...@@ -356,7 +357,7 @@ class PackageInfo:
return info return info
@staticmethod @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. Discover all `*.*-info` directories in a given path.
...@@ -372,7 +373,7 @@ class PackageInfo: ...@@ -372,7 +373,7 @@ class PackageInfo:
yield Path(d) yield Path(d)
@classmethod @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. Helper method to parse package information from an unpacked metadata directory.
...@@ -406,7 +407,7 @@ class PackageInfo: ...@@ -406,7 +407,7 @@ class PackageInfo:
return info return info
@classmethod @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. Helper method to inspect a `Package` object, in order to generate package info.
...@@ -429,14 +430,14 @@ class PackageInfo: ...@@ -429,14 +430,14 @@ class PackageInfo:
) )
@staticmethod @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 # Note: we ignore any setup.py file at this step
# TODO: add support for handling non-poetry PEP-517 builds # TODO: add support for handling non-poetry PEP-517 builds
if PyProjectTOML(path.joinpath("pyproject.toml")).is_poetry_project(): if PyProjectTOML(path.joinpath("pyproject.toml")).is_poetry_project():
return Factory().create_poetry(path).package return Factory().create_poetry(path).package
@classmethod @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. Helper method to use PEP-517 library to build and read package metadata.
...@@ -511,9 +512,7 @@ class PackageInfo: ...@@ -511,9 +512,7 @@ class PackageInfo:
raise PackageInfoError(path, "Exhausted all core metadata sources.") raise PackageInfoError(path, "Exhausted all core metadata sources.")
@classmethod @classmethod
def from_directory( def from_directory(cls, path: Path, disable_build: bool = False) -> "PackageInfo":
cls, path, disable_build=False
): # type: (Path, bool) -> PackageInfo
""" """
Generate package information from a package source directory. If `disable_build` is not `True` and 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 introspection of all available metadata fails, the package is attempted to be build in an isolated
...@@ -547,7 +546,7 @@ class PackageInfo: ...@@ -547,7 +546,7 @@ class PackageInfo:
return info return info
@classmethod @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. Gather package information from an sdist file, packed or unpacked.
...@@ -561,7 +560,7 @@ class PackageInfo: ...@@ -561,7 +560,7 @@ class PackageInfo:
return cls.from_directory(path=path) return cls.from_directory(path=path)
@classmethod @classmethod
def from_wheel(cls, path): # type: (Path) -> PackageInfo def from_wheel(cls, path: Path) -> "PackageInfo":
""" """
Gather package information from a wheel. Gather package information from a wheel.
...@@ -573,7 +572,7 @@ class PackageInfo: ...@@ -573,7 +572,7 @@ class PackageInfo:
return PackageInfo() return PackageInfo()
@classmethod @classmethod
def from_bdist(cls, path): # type: (Path) -> PackageInfo def from_bdist(cls, path: Path) -> "PackageInfo":
""" """
Gather package information from a bdist (wheel etc.). Gather package information from a bdist (wheel etc.).
...@@ -591,7 +590,7 @@ class PackageInfo: ...@@ -591,7 +590,7 @@ class PackageInfo:
raise PackageInfoError(path, e) raise PackageInfoError(path, e)
@classmethod @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). Gather package information from a given path (bdist, sdist, directory).
......
...@@ -3,6 +3,9 @@ import time ...@@ -3,6 +3,9 @@ import time
import urllib.parse import urllib.parse
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
from typing import Optional
from typing import Tuple
import requests import requests
import requests.auth import requests.auth
...@@ -13,10 +16,6 @@ from poetry.utils.password_manager import PasswordManager ...@@ -13,10 +16,6 @@ from poetry.utils.password_manager import PasswordManager
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any
from typing import Optional
from typing import Tuple
from cleo.io.io import IO from cleo.io.io import IO
from poetry.config.config import Config from poetry.config.config import Config
...@@ -26,14 +25,14 @@ logger = logging.getLogger() ...@@ -26,14 +25,14 @@ logger = logging.getLogger()
class Authenticator(object): 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._config = config
self._io = io self._io = io
self._session = None self._session = None
self._credentials = {} self._credentials = {}
self._password_manager = PasswordManager(self._config) 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: if self._io is not None:
self._io.write_line( self._io.write_line(
"<{level:s}>{message:s}</{level:s}>".format( "<{level:s}>{message:s}</{level:s}>".format(
...@@ -44,15 +43,13 @@ class Authenticator(object): ...@@ -44,15 +43,13 @@ class Authenticator(object):
getattr(logger, level, logger.debug)(message) getattr(logger, level, logger.debug)(message)
@property @property
def session(self): # type: () -> requests.Session def session(self) -> requests.Session:
if self._session is None: if self._session is None:
self._session = requests.Session() self._session = requests.Session()
return self._session return self._session
def request( def request(self, method: str, url: str, **kwargs: Any) -> requests.Response:
self, method, url, **kwargs
): # type: (str, str, Any) -> requests.Response
request = requests.Request(method, url) request = requests.Request(method, url)
username, password = self.get_credentials_for_url(url) username, password = self.get_credentials_for_url(url)
...@@ -104,9 +101,7 @@ class Authenticator(object): ...@@ -104,9 +101,7 @@ class Authenticator(object):
# this should never really be hit under any sane circumstance # this should never really be hit under any sane circumstance
raise PoetryException("Failed HTTP {} request", method.upper()) raise PoetryException("Failed HTTP {} request", method.upper())
def get_credentials_for_url( def get_credentials_for_url(self, url: str) -> Tuple[Optional[str], Optional[str]]:
self, url
): # type: (str) -> Tuple[Optional[str], Optional[str]]
parsed_url = urllib.parse.urlsplit(url) parsed_url = urllib.parse.urlsplit(url)
netloc = parsed_url.netloc netloc = parsed_url.netloc
...@@ -141,8 +136,8 @@ class Authenticator(object): ...@@ -141,8 +136,8 @@ class Authenticator(object):
return credentials[0], credentials[1] return credentials[0], credentials[1]
def _get_credentials_for_netloc_from_config( def _get_credentials_for_netloc_from_config(
self, netloc self, netloc: str
): # type: (str) -> Tuple[Optional[str], Optional[str]] ) -> Tuple[Optional[str], Optional[str]]:
credentials = (None, None) credentials = (None, None)
for repository_name in self._config.get("repositories", []): for repository_name in self._config.get("repositories", []):
......
...@@ -2,15 +2,15 @@ from typing import TYPE_CHECKING ...@@ -2,15 +2,15 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class BaseInstaller: class BaseInstaller:
def install(self, package): # type: ("Package") -> None def install(self, package: "Package") -> None:
raise NotImplementedError raise NotImplementedError
def update(self, source, target): # type: ("Package", "Package") -> None def update(self, source: "Package", target: "Package") -> None:
raise NotImplementedError raise NotImplementedError
def remove(self, package): # type: ("Package") -> None def remove(self, package: "Package") -> None:
raise NotImplementedError raise NotImplementedError
...@@ -3,6 +3,8 @@ import json ...@@ -3,6 +3,8 @@ import json
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import List
from typing import Optional
from poetry.core.packages.utils.link import Link from poetry.core.packages.utils.link import Link
...@@ -11,37 +13,35 @@ from .chooser import Wheel ...@@ -11,37 +13,35 @@ from .chooser import Wheel
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import List
from typing import Optional
from poetry.config.config import Config from poetry.config.config import Config
from poetry.utils.env import Env from poetry.utils.env import Env
class Chef: class Chef:
def __init__(self, config, env): # type: (Config, Env) -> None def __init__(self, config: "Config", env: "Env") -> None:
self._config = config self._config = config
self._env = env self._env = env
self._cache_dir = ( self._cache_dir = (
Path(config.get("cache-dir")).expanduser().joinpath("artifacts") Path(config.get("cache-dir")).expanduser().joinpath("artifacts")
) )
def prepare(self, archive): # type: (Path) -> Path def prepare(self, archive: Path) -> Path:
return archive return archive
def prepare_sdist(self, archive): # type: (Path) -> Path def prepare_sdist(self, archive: Path) -> Path:
return archive return archive
def prepare_wheel(self, archive): # type: (Path) -> Path def prepare_wheel(self, archive: Path) -> Path:
return archive return archive
def should_prepare(self, archive): # type: (Path) -> bool def should_prepare(self, archive: Path) -> bool:
return not self.is_wheel(archive) 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" 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 the archive is already a wheel, there is no need to cache it.
if link.is_wheel: if link.is_wheel:
pass pass
...@@ -74,7 +74,7 @@ class Chef: ...@@ -74,7 +74,7 @@ class Chef:
return min(candidates)[1] 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) cache_dir = self.get_cache_directory_for_link(link)
archive_types = ["whl", "tar.gz", "tar.bz2", "bz2", "zip"] archive_types = ["whl", "tar.gz", "tar.bz2", "bz2", "zip"]
...@@ -85,7 +85,7 @@ class Chef: ...@@ -85,7 +85,7 @@ class Chef:
return links 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} key_parts = {"url": link.url_without_fragment}
if link.hash_name is not None and link.hash is not None: if link.hash_name is not None and link.hash is not None:
......
...@@ -18,7 +18,7 @@ class InvalidWheelName(Exception): ...@@ -18,7 +18,7 @@ class InvalidWheelName(Exception):
class Wheel(object): class Wheel(object):
def __init__(self, filename): # type: (str) -> None def __init__(self, filename: str) -> None:
wheel_info = wheel_file_re.match(filename) wheel_info = wheel_file_re.match(filename)
if not wheel_info: if not wheel_info:
raise InvalidWheelName("{} is not a valid wheel filename.".format(filename)) raise InvalidWheelName("{} is not a valid wheel filename.".format(filename))
...@@ -35,12 +35,12 @@ class Wheel(object): ...@@ -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 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] indexes = [tags.index(t) for t in self.tags if t in tags]
return min(indexes) if indexes else None 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)) return bool(set(env.supported_tags).intersection(self.tags))
...@@ -49,11 +49,11 @@ class Chooser: ...@@ -49,11 +49,11 @@ class Chooser:
A Chooser chooses an appropriate release archive for packages. 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._pool = pool
self._env = env 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. Return the url of the selected archive for a given package.
""" """
...@@ -83,7 +83,7 @@ class Chooser: ...@@ -83,7 +83,7 @@ class Chooser:
return chosen 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 package.source_type:
if not self._pool.has_repository("pypi"): if not self._pool.has_repository("pypi"):
repository = self._pool.repositories[0] repository = self._pool.repositories[0]
...@@ -112,7 +112,7 @@ class Chooser: ...@@ -112,7 +112,7 @@ class Chooser:
return selected_links 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 Function to pass as the `key` argument to a call to sorted() to sort
InstallationCandidates by preference. InstallationCandidates by preference.
...@@ -170,9 +170,7 @@ class Chooser: ...@@ -170,9 +170,7 @@ class Chooser:
pri, pri,
) )
def _is_link_hash_allowed_for_package( def _is_link_hash_allowed_for_package(self, link: Link, package: Package) -> bool:
self, link, package
): # type: (Link, Package) -> bool
if not link.hash: if not link.hash:
return True return True
......
...@@ -35,17 +35,22 @@ from .operations.update import Update ...@@ -35,17 +35,22 @@ from .operations.update import Update
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.io.io import IO # noqa from cleo.io.io import IO # noqa
from poetry.config.config import Config # noqa from poetry.config.config import Config
from poetry.repositories import Pool # noqa from poetry.repositories import Pool
from poetry.utils.env import Env # noqa from poetry.utils.env import Env
from .operations import OperationTypes # noqa from .operations import OperationTypes
class Executor(object): class Executor(object):
def __init__( def __init__(
self, env, pool, config, io, parallel=None self,
): # type: ("Env", "Pool", "Config", "IO", bool) -> None env: "Env",
pool: "Pool",
config: "Config",
io: "IO",
parallel: bool = None,
) -> None:
self._env = env self._env = env
self._io = io self._io = io
self._dry_run = False self._dry_run = False
...@@ -80,36 +85,36 @@ class Executor(object): ...@@ -80,36 +85,36 @@ class Executor(object):
self._shutdown = False self._shutdown = False
@property @property
def installations_count(self): # type: () -> int def installations_count(self) -> int:
return self._executed["install"] return self._executed["install"]
@property @property
def updates_count(self): # type: () -> int def updates_count(self) -> int:
return self._executed["update"] return self._executed["update"]
@property @property
def removals_count(self): # type: () -> int def removals_count(self) -> int:
return self._executed["uninstall"] 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 return self._io.output.is_decorated() and not self._dry_run
def disable(self): # type: () -> "Executor" def disable(self) -> "Executor":
self._enabled = False self._enabled = False
return self 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 self._dry_run = dry_run
return self return self
def verbose(self, verbose=True): # type: (bool) -> Executor def verbose(self, verbose: bool = True) -> "Executor":
self._verbose = verbose self._verbose = verbose
return self return self
def execute(self, operations): # type: (List["OperationTypes"]) -> int def execute(self, operations: List["OperationTypes"]) -> int:
self._total_operations = len(operations) self._total_operations = len(operations)
for job_type in self._executed: for job_type in self._executed:
self._executed[job_type] = 0 self._executed[job_type] = 0
...@@ -162,7 +167,7 @@ class Executor(object): ...@@ -162,7 +167,7 @@ class Executor(object):
return 1 if self._shutdown else 0 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( if not self.supports_fancy_output() or not self._should_write_operation(
operation operation
): ):
...@@ -180,7 +185,7 @@ class Executor(object): ...@@ -180,7 +185,7 @@ class Executor(object):
section.clear() section.clear()
section.write(line) section.write(line)
def _execute_operation(self, operation): # type: ("OperationTypes") -> None def _execute_operation(self, operation: "OperationTypes") -> None:
try: try:
if self.supports_fancy_output(): if self.supports_fancy_output():
if id(operation) not in self._sections: if id(operation) not in self._sections:
...@@ -259,7 +264,7 @@ class Executor(object): ...@@ -259,7 +264,7 @@ class Executor(object):
with self._lock: with self._lock:
self._shutdown = True self._shutdown = True
def _do_execute_operation(self, operation): # type: ("OperationTypes") -> int def _do_execute_operation(self, operation: "OperationTypes") -> int:
method = operation.job_type method = operation.job_type
operation_message = self.get_operation_message(operation) operation_message = self.get_operation_message(operation)
...@@ -304,8 +309,8 @@ class Executor(object): ...@@ -304,8 +309,8 @@ class Executor(object):
return result return result
def _increment_operations_count( def _increment_operations_count(
self, operation, executed self, operation: "OperationTypes", executed: bool
): # type: ("OperationTypes", bool) -> None ) -> None:
with self._lock: with self._lock:
if executed: if executed:
self._executed_operations += 1 self._executed_operations += 1
...@@ -313,7 +318,7 @@ class Executor(object): ...@@ -313,7 +318,7 @@ class Executor(object):
else: else:
self._skipped[operation.job_type] += 1 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: try:
self._env.run_pip(*args, **kwargs) self._env.run_pip(*args, **kwargs)
except EnvCommandError as e: except EnvCommandError as e:
...@@ -329,8 +334,12 @@ class Executor(object): ...@@ -329,8 +334,12 @@ class Executor(object):
return 0 return 0
def get_operation_message( def get_operation_message(
self, operation, done=False, error=False, warning=False self,
): # type: ("OperationTypes", bool, bool, bool) -> str operation: "OperationTypes",
done: bool = False,
error: bool = False,
warning: bool = False,
) -> str:
base_tag = "fg=default" base_tag = "fg=default"
operation_color = "c2" operation_color = "c2"
source_operation_color = "c2" source_operation_color = "c2"
...@@ -384,7 +393,7 @@ class Executor(object): ...@@ -384,7 +393,7 @@ class Executor(object):
return "" return ""
def _display_summary(self, operations): # type: (List["OperationTypes"]) -> None def _display_summary(self, operations: List["OperationTypes"]) -> None:
installs = 0 installs = 0
updates = 0 updates = 0
uninstalls = 0 uninstalls = 0
...@@ -427,13 +436,13 @@ class Executor(object): ...@@ -427,13 +436,13 @@ class Executor(object):
) )
self._io.write_line("") 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) 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) return self._update(operation)
def _execute_uninstall(self, operation): # type: (Uninstall) -> int def _execute_uninstall(self, operation: Uninstall) -> int:
message = ( message = (
" <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format( " <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format(
message=self.get_operation_message(operation), message=self.get_operation_message(operation),
...@@ -443,7 +452,7 @@ class Executor(object): ...@@ -443,7 +452,7 @@ class Executor(object):
return self._remove(operation) return self._remove(operation)
def _install(self, operation): # type: (Union[Install, Update]) -> int def _install(self, operation: Union[Install, Update]) -> int:
package = operation.package package = operation.package
if package.source_type == "directory": if package.source_type == "directory":
return self._install_directory(operation) return self._install_directory(operation)
...@@ -472,10 +481,10 @@ class Executor(object): ...@@ -472,10 +481,10 @@ class Executor(object):
return self.run_pip(*args) 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) return self._install(operation)
def _remove(self, operation): # type: (Uninstall) -> int def _remove(self, operation: Uninstall) -> int:
package = operation.package package = operation.package
# If we have a VCS package, remove its source directory # If we have a VCS package, remove its source directory
...@@ -492,7 +501,7 @@ class Executor(object): ...@@ -492,7 +501,7 @@ class Executor(object):
raise raise
def _prepare_file(self, operation): # type: (Union[Install, Update]) -> Path def _prepare_file(self, operation: Union[Install, Update]) -> Path:
package = operation.package package = operation.package
message = ( message = (
...@@ -510,7 +519,7 @@ class Executor(object): ...@@ -510,7 +519,7 @@ class Executor(object):
return archive 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 from poetry.factory import Factory
package = operation.package package = operation.package
...@@ -576,7 +585,7 @@ class Executor(object): ...@@ -576,7 +585,7 @@ class Executor(object):
return self.run_pip(*args) 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 from poetry.core.vcs import Git
package = operation.package package = operation.package
...@@ -604,14 +613,12 @@ class Executor(object): ...@@ -604,14 +613,12 @@ class Executor(object):
return self._install_directory(operation) 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) link = self._chooser.choose_for(operation.package)
return self._download_link(operation, link) return self._download_link(operation, link)
def _download_link( def _download_link(self, operation: Union[Install, Update], link: Link) -> Link:
self, operation, link
): # type: (Union[Install, Update], Link) -> Link
package = operation.package package = operation.package
archive = self._chef.get_cached_archive_for_link(link) archive = self._chef.get_cached_archive_for_link(link)
...@@ -643,9 +650,7 @@ class Executor(object): ...@@ -643,9 +650,7 @@ class Executor(object):
return archive return archive
def _download_archive( def _download_archive(self, operation: Union[Install, Update], link: Link) -> Path:
self, operation, link
): # type: (Union[Install, Update], Link) -> Path
response = self._authenticator.request( response = self._authenticator.request(
"get", link.url, stream=True, io=self._sections.get(id(operation), self._io) "get", link.url, stream=True, io=self._sections.get(id(operation), self._io)
) )
...@@ -694,7 +699,7 @@ class Executor(object): ...@@ -694,7 +699,7 @@ class Executor(object):
return archive return archive
def _should_write_operation(self, operation): # type: (Operation) -> bool def _should_write_operation(self, operation: Operation) -> bool:
if not operation.skipped: if not operation.skipped:
return True return True
......
...@@ -26,22 +26,22 @@ from .pip_installer import PipInstaller ...@@ -26,22 +26,22 @@ from .pip_installer import PipInstaller
if TYPE_CHECKING: 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: class Installer:
def __init__( def __init__(
self, self,
io, # type: IO io: IO,
env, # type: "Env" env: "Env",
package, # type: ProjectPackage package: ProjectPackage,
locker, # type: Locker locker: Locker,
pool, # type: Pool pool: Pool,
config, # type: Config config: Config,
installed=None, # type: Union[InstalledRepository, None] installed: Union[InstalledRepository, None] = None,
executor=None, # type: Optional[Executor] executor: Optional[Executor] = None,
): ):
self._io = io self._io = io
self._env = env self._env = env
...@@ -76,24 +76,24 @@ class Installer: ...@@ -76,24 +76,24 @@ class Installer:
self._installed_repository = installed self._installed_repository = installed
@property @property
def executor(self): # type: () -> Executor def executor(self) -> Executor:
return self._executor return self._executor
@property @property
def installer(self): # type: () -> BaseInstaller def installer(self) -> BaseInstaller:
return self._installer return self._installer
def set_package(self, package): # type: (ProjectPackage) -> Installer def set_package(self, package: ProjectPackage) -> "Installer":
self._package = package self._package = package
return self return self
def set_locker(self, locker): # type: (Locker) -> Installer def set_locker(self, locker: Locker) -> "Installer":
self._locker = locker self._locker = locker
return self return self
def run(self): # type: () -> int def run(self) -> int:
# Check if refresh # Check if refresh
if not self._update and self._lock and self._locker.is_locked(): if not self._update and self._lock and self._locker.is_locked():
return self._do_refresh() return self._do_refresh()
...@@ -111,54 +111,54 @@ class Installer: ...@@ -111,54 +111,54 @@ class Installer:
return self._do_install(local_repo) 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._dry_run = dry_run
self._executor.dry_run(dry_run) self._executor.dry_run(dry_run)
return self return self
def is_dry_run(self): # type: () -> bool def is_dry_run(self) -> bool:
return self._dry_run 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 self._remove_untracked = remove_untracked
return self return self
def is_remove_untracked(self): # type: () -> bool def is_remove_untracked(self) -> bool:
return self._remove_untracked return self._remove_untracked
def verbose(self, verbose=True): # type: (bool) -> Installer def verbose(self, verbose: bool = True) -> "Installer":
self._verbose = verbose self._verbose = verbose
self._executor.verbose(verbose) self._executor.verbose(verbose)
return self return self
def is_verbose(self): # type: () -> bool def is_verbose(self) -> bool:
return self._verbose 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 self._dev_mode = dev_mode
return self return self
def is_dev_mode(self): # type: () -> bool def is_dev_mode(self) -> bool:
return self._dev_mode 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 self._dev_only = dev_only
return self return self
def is_dev_only(self): # type: () -> bool def is_dev_only(self) -> bool:
return self._dev_only return self._dev_only
def update(self, update=True): # type: (bool) -> Installer def update(self, update: bool = True) -> "Installer":
self._update = update self._update = update
return self return self
def lock(self, update=True): # type: (bool) -> Installer def lock(self, update: bool = True) -> "Installer":
""" """
Prepare the installer for locking only. Prepare the installer for locking only.
""" """
...@@ -168,10 +168,10 @@ class Installer: ...@@ -168,10 +168,10 @@ class Installer:
return self return self
def is_updating(self): # type: () -> bool def is_updating(self) -> bool:
return self._update return self._update
def execute_operations(self, execute=True): # type: (bool) -> Installer def execute_operations(self, execute: bool = True) -> "Installer":
self._execute_operations = execute self._execute_operations = execute
if not execute: if not execute:
...@@ -179,22 +179,22 @@ class Installer: ...@@ -179,22 +179,22 @@ class Installer:
return self 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] self._whitelist = [canonicalize_name(p) for p in packages]
return self return self
def extras(self, extras): # type: (list) -> Installer def extras(self, extras: list) -> "Installer":
self._extras = extras self._extras = extras
return self 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 self._use_executor = use_executor
return self return self
def _do_refresh(self): # type: () -> int def _do_refresh(self) -> int:
from poetry.puzzle import Solver from poetry.puzzle import Solver
# Checking extras # Checking extras
...@@ -208,7 +208,7 @@ class Installer: ...@@ -208,7 +208,7 @@ class Installer:
self._pool, self._pool,
locked_repository, locked_repository,
locked_repository, locked_repository,
self._io, # noqa self._io,
) )
ops = solver.solve(use_latest=[]) ops = solver.solve(use_latest=[])
...@@ -220,7 +220,7 @@ class Installer: ...@@ -220,7 +220,7 @@ class Installer:
return 0 return 0
def _do_install(self, local_repo): # type: (Repository) -> int def _do_install(self, local_repo: Repository) -> int:
from poetry.puzzle import Solver from poetry.puzzle import Solver
locked_repository = Repository() locked_repository = Repository()
...@@ -335,7 +335,7 @@ class Installer: ...@@ -335,7 +335,7 @@ class Installer:
# Execute operations # Execute operations
return self._execute(ops) 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): if force or (self._update and self._write_lock):
updated_lock = self._locker.set_lock_data(self._package, repo.packages) updated_lock = self._locker.set_lock_data(self._package, repo.packages)
...@@ -343,7 +343,7 @@ class Installer: ...@@ -343,7 +343,7 @@ class Installer:
self._io.write_line("") self._io.write_line("")
self._io.write_line("<info>Writing lock file</>") 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: if self._use_executor:
return self._executor.execute(operations) return self._executor.execute(operations)
...@@ -391,7 +391,7 @@ class Installer: ...@@ -391,7 +391,7 @@ class Installer:
return 0 return 0
def _execute_operation(self, operation): # type: (Operation) -> None def _execute_operation(self, operation: Operation) -> None:
""" """
Execute a given operation. Execute a given operation.
""" """
...@@ -399,7 +399,7 @@ class Installer: ...@@ -399,7 +399,7 @@ class Installer:
getattr(self, "_execute_{}".format(method))(operation) 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 operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()): if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.write_line( self._io.write_line(
...@@ -424,7 +424,7 @@ class Installer: ...@@ -424,7 +424,7 @@ class Installer:
self._installer.install(operation.package) self._installer.install(operation.package)
def _execute_update(self, operation): # type: (Update) -> None def _execute_update(self, operation: Update) -> None:
source = operation.initial_package source = operation.initial_package
target = operation.target_package target = operation.target_package
...@@ -454,7 +454,7 @@ class Installer: ...@@ -454,7 +454,7 @@ class Installer:
self._installer.update(source, target) self._installer.update(source, target)
def _execute_uninstall(self, operation): # type: (Uninstall) -> None def _execute_uninstall(self, operation: Uninstall) -> None:
if operation.skipped: if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()): if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.write_line( self._io.write_line(
...@@ -480,8 +480,8 @@ class Installer: ...@@ -480,8 +480,8 @@ class Installer:
self._installer.remove(operation.package) self._installer.remove(operation.package)
def _populate_local_repo( def _populate_local_repo(
self, local_repo, ops self, local_repo: Repository, ops: List[Operation]
): # type: (Repository, List[Operation]) -> None ) -> None:
for op in ops: for op in ops:
if isinstance(op, Uninstall): if isinstance(op, Uninstall):
continue continue
...@@ -494,8 +494,8 @@ class Installer: ...@@ -494,8 +494,8 @@ class Installer:
local_repo.add_package(package) local_repo.add_package(package)
def _get_operations_from_lock( def _get_operations_from_lock(
self, locked_repository self, locked_repository: Repository
): # type: (Repository) -> List[Operation] ) -> List[Operation]:
installed_repo = self._installed_repository installed_repo = self._installed_repository
ops = [] ops = []
...@@ -526,9 +526,7 @@ class Installer: ...@@ -526,9 +526,7 @@ class Installer:
return ops return ops
def _filter_operations( def _filter_operations(self, ops: List[Operation], repo: Repository) -> None:
self, ops, repo
): # type: (List[Operation], Repository) -> None
extra_packages = self._get_extra_packages(repo) extra_packages = self._get_extra_packages(repo)
for op in ops: for op in ops:
if isinstance(op, Update): if isinstance(op, Update):
...@@ -563,7 +561,7 @@ class Installer: ...@@ -563,7 +561,7 @@ class Installer:
if package.category == "dev" and not self.is_dev_mode(): if package.category == "dev" and not self.is_dev_mode():
op.skip("Dev dependencies not requested") 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. Returns all package names required by extras.
...@@ -576,8 +574,8 @@ class Installer: ...@@ -576,8 +574,8 @@ class Installer:
return list(get_extra_package_names(repo.packages, extras, self._extras)) 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) return PipInstaller(self._env, self._io, self._pool)
def _get_installed(self): # type: () -> InstalledRepository def _get_installed(self) -> InstalledRepository:
return InstalledRepository.load(self._env) return InstalledRepository.load(self._env)
...@@ -5,32 +5,32 @@ from .base_installer import BaseInstaller ...@@ -5,32 +5,32 @@ from .base_installer import BaseInstaller
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class NoopInstaller(BaseInstaller): class NoopInstaller(BaseInstaller):
def __init__(self): # type: () -> None def __init__(self) -> None:
self._installs = [] self._installs = []
self._updates = [] self._updates = []
self._removals = [] self._removals = []
@property @property
def installs(self): # type: () -> List["Package"] def installs(self) -> List["Package"]:
return self._installs return self._installs
@property @property
def updates(self): # type: () -> List["Package"] def updates(self) -> List["Package"]:
return self._updates return self._updates
@property @property
def removals(self): # type: () -> List["Package"] def removals(self) -> List["Package"]:
return self._removals return self._removals
def install(self, package): # type: ("Package") -> None def install(self, package: "Package") -> None:
self._installs.append(package) 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)) self._updates.append((source, target))
def remove(self, package): # type: ("Package") -> None def remove(self, package: "Package") -> None:
self._removals.append(package) self._removals.append(package)
...@@ -5,31 +5,31 @@ from .operation import Operation ...@@ -5,31 +5,31 @@ from .operation import Operation
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Install(Operation): class Install(Operation):
def __init__( def __init__(
self, package, reason=None, priority=0 self, package: "Package", reason: Optional[str] = None, priority: int = 0
): # type: ("Package", Optional[str], int) -> None ) -> None:
super(Install, self).__init__(reason, priority=priority) super(Install, self).__init__(reason, priority=priority)
self._package = package self._package = package
@property @property
def package(self): # type: () -> "Package" def package(self) -> "Package":
return self._package return self._package
@property @property
def job_type(self): # type: () -> str def job_type(self) -> str:
return "install" return "install"
def __str__(self): # type: () -> str def __str__(self) -> str:
return "Installing {} ({})".format( return "Installing {} ({})".format(
self.package.pretty_name, self.format_version(self.package) self.package.pretty_name, self.format_version(self.package)
) )
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return "<Install {} ({})>".format( return "<Install {} ({})>".format(
self.package.pretty_name, self.format_version(self.package) self.package.pretty_name, self.format_version(self.package)
) )
...@@ -5,11 +5,11 @@ from typing import Optional ...@@ -5,11 +5,11 @@ from typing import Optional
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Operation(object): 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._reason = reason
self._skipped = False self._skipped = False
...@@ -17,39 +17,39 @@ class Operation(object): ...@@ -17,39 +17,39 @@ class Operation(object):
self._priority = priority self._priority = priority
@property @property
def job_type(self): # type: () -> str def job_type(self) -> str:
raise NotImplementedError raise NotImplementedError
@property @property
def reason(self): # type: () -> str def reason(self) -> str:
return self._reason return self._reason
@property @property
def skipped(self): # type: () -> bool def skipped(self) -> bool:
return self._skipped return self._skipped
@property @property
def skip_reason(self): # type: () -> Optional[str] def skip_reason(self) -> Optional[str]:
return self._skip_reason return self._skip_reason
@property @property
def priority(self): # type: () -> int def priority(self) -> int:
return self._priority return self._priority
@property @property
def package(self): # type: () -> "Package" def package(self) -> "Package":
raise NotImplementedError() raise NotImplementedError()
def format_version(self, package): # type: ("Package") -> str def format_version(self, package: "Package") -> str:
return package.full_pretty_version return package.full_pretty_version
def skip(self, reason): # type: (str) -> Operation def skip(self, reason: str) -> "Operation":
self._skipped = True self._skipped = True
self._skip_reason = reason self._skip_reason = reason
return self return self
def unskip(self): # type: () -> Operation def unskip(self) -> "Operation":
self._skipped = False self._skipped = False
self._skip_reason = None self._skip_reason = None
......
...@@ -5,31 +5,34 @@ from .operation import Operation ...@@ -5,31 +5,34 @@ from .operation import Operation
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Uninstall(Operation): class Uninstall(Operation):
def __init__( def __init__(
self, package, reason=None, priority=float("inf") self,
): # type: ("Package", Optional[str], int) -> None package: "Package",
reason: Optional[str] = None,
priority: int = float("inf"),
) -> None:
super(Uninstall, self).__init__(reason, priority=priority) super(Uninstall, self).__init__(reason, priority=priority)
self._package = package self._package = package
@property @property
def package(self): # type: () -> "Package" def package(self) -> "Package":
return self._package return self._package
@property @property
def job_type(self): # type: () -> str def job_type(self) -> str:
return "uninstall" return "uninstall"
def __str__(self): # type: () -> str def __str__(self) -> str:
return "Uninstalling {} ({})".format( return "Uninstalling {} ({})".format(
self.package.pretty_name, self.format_version(self._package) self.package.pretty_name, self.format_version(self._package)
) )
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return "<Uninstall {} ({})>".format( return "<Uninstall {} ({})>".format(
self.package.pretty_name, self.format_version(self.package) self.package.pretty_name, self.format_version(self.package)
) )
...@@ -5,35 +5,39 @@ from .operation import Operation ...@@ -5,35 +5,39 @@ from .operation import Operation
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Update(Operation): class Update(Operation):
def __init__( def __init__(
self, initial, target, reason=None, priority=0 self,
): # type: ("Package", "Package", Optional[str], int) -> None initial: "Package",
target: "Package",
reason: Optional[str] = None,
priority: int = 0,
) -> None:
self._initial_package = initial self._initial_package = initial
self._target_package = target self._target_package = target
super(Update, self).__init__(reason, priority=priority) super(Update, self).__init__(reason, priority=priority)
@property @property
def initial_package(self): # type: () -> "Package" def initial_package(self) -> "Package":
return self._initial_package return self._initial_package
@property @property
def target_package(self): # type: () -> "Package" def target_package(self) -> "Package":
return self._target_package return self._target_package
@property @property
def package(self): # type: () -> "Package" def package(self) -> "Package":
return self._target_package return self._target_package
@property @property
def job_type(self): # type: () -> str def job_type(self) -> str:
return "update" return "update"
def __str__(self): # type: () -> str def __str__(self) -> str:
return "Updating {} ({}) to {} ({})".format( return "Updating {} ({}) to {} ({})".format(
self.initial_package.pretty_name, self.initial_package.pretty_name,
self.format_version(self.initial_package), self.format_version(self.initial_package),
...@@ -41,7 +45,7 @@ class Update(Operation): ...@@ -41,7 +45,7 @@ class Update(Operation):
self.format_version(self.target_package), self.format_version(self.target_package),
) )
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return "<Update {} ({}) to {} ({})>".format( return "<Update {} ({}) to {} ({})>".format(
self.initial_package.pretty_name, self.initial_package.pretty_name,
self.format_version(self.initial_package), self.format_version(self.initial_package),
......
...@@ -19,16 +19,16 @@ from .base_installer import BaseInstaller ...@@ -19,16 +19,16 @@ from .base_installer import BaseInstaller
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class PipInstaller(BaseInstaller): 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._env = env
self._io = io self._io = io
self._pool = pool 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": if package.source_type == "directory":
self.install_directory(package) self.install_directory(package)
...@@ -48,7 +48,7 @@ class PipInstaller(BaseInstaller): ...@@ -48,7 +48,7 @@ class PipInstaller(BaseInstaller):
repository = self._pool.repository(package.source_reference) repository = self._pool.repository(package.source_reference)
parsed = urllib.parse.urlparse(package.source_url) parsed = urllib.parse.urlparse(package.source_url)
if parsed.scheme == "http": if parsed.scheme == "http":
self._io.error( self._io.write_error(
" <warning>Installing from unsecure host: {}</warning>".format( " <warning>Installing from unsecure host: {}</warning>".format(
parsed.hostname parsed.hostname
) )
...@@ -97,7 +97,7 @@ class PipInstaller(BaseInstaller): ...@@ -97,7 +97,7 @@ class PipInstaller(BaseInstaller):
self.run(*args) 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 package.source_type != target.source_type:
# If the source type has changed, we remove the current # If the source type has changed, we remove the current
# package to avoid perpetual updates in some cases # package to avoid perpetual updates in some cases
...@@ -105,7 +105,7 @@ class PipInstaller(BaseInstaller): ...@@ -105,7 +105,7 @@ class PipInstaller(BaseInstaller):
self.install(target, update=True) self.install(target, update=True)
def remove(self, package): # type: ("Package") -> None def remove(self, package: "Package") -> None:
try: try:
self.run("uninstall", package.name, "-y") self.run("uninstall", package.name, "-y")
except CalledProcessError as e: except CalledProcessError as e:
...@@ -127,10 +127,10 @@ class PipInstaller(BaseInstaller): ...@@ -127,10 +127,10 @@ class PipInstaller(BaseInstaller):
if src_dir.exists(): if src_dir.exists():
safe_rmtree(str(src_dir)) 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) 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: if formatted and not package.source_type:
req = "{}=={}".format(package.name, package.version) req = "{}=={}".format(package.name, package.version)
for f in package.files: for f in package.files:
...@@ -171,7 +171,7 @@ class PipInstaller(BaseInstaller): ...@@ -171,7 +171,7 @@ class PipInstaller(BaseInstaller):
return "{}=={}".format(package.name, package.version) 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( fd, name = tempfile.mkstemp(
"reqs.txt", "{}-{}".format(package.name, package.version) "reqs.txt", "{}-{}".format(package.name, package.version)
) )
...@@ -183,7 +183,7 @@ class PipInstaller(BaseInstaller): ...@@ -183,7 +183,7 @@ class PipInstaller(BaseInstaller):
return name 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 cleo.io.null_io import NullIO
from poetry.factory import Factory from poetry.factory import Factory
...@@ -241,7 +241,7 @@ class PipInstaller(BaseInstaller): ...@@ -241,7 +241,7 @@ class PipInstaller(BaseInstaller):
return self.run(*args) 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.packages import Package
from poetry.core.vcs import Git from poetry.core.vcs import Git
......
...@@ -15,7 +15,7 @@ class ValidationError(ValueError): ...@@ -15,7 +15,7 @@ class ValidationError(ValueError):
pass 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)) schema = os.path.join(SCHEMA_DIR, "{}.json".format(schema_name))
if not os.path.exists(schema): if not os.path.exists(schema):
......
...@@ -8,7 +8,7 @@ from .standard import StandardLayout ...@@ -8,7 +8,7 @@ from .standard import StandardLayout
_LAYOUTS = {"src": SrcLayout, "standard": StandardLayout} _LAYOUTS = {"src": SrcLayout, "standard": StandardLayout}
def layout(name): # type: (str) -> Type[Layout] def layout(name: str) -> Type[Layout]:
if name not in _LAYOUTS: if name not in _LAYOUTS:
raise ValueError("Invalid layout") raise ValueError("Invalid layout")
......
...@@ -10,8 +10,9 @@ from poetry.utils.helpers import module_name ...@@ -10,8 +10,9 @@ from poetry.utils.helpers import module_name
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.pyproject.toml import PyProjectTOML # noqa from pathlib import Path
from poetry.utils._compat import Path # noqa
from poetry.core.pyproject.toml import PyProjectTOML
TESTS_DEFAULT = u"""from {package_name} import __version__ TESTS_DEFAULT = u"""from {package_name} import __version__
...@@ -47,21 +48,21 @@ license = "" ...@@ -47,21 +48,21 @@ license = ""
""" """
BUILD_SYSTEM_MIN_VERSION = "1.0.0" 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): class Layout(object):
def __init__( def __init__(
self, self,
project, # type: str project: str,
version="0.1.0", # type: str version: str = "0.1.0",
description="", # type: str description: str = "",
readme_format="md", # type: str readme_format: str = "md",
author=None, # type: Optional[str] author: Optional[str] = None,
license=None, # type: Optional[str] license: Optional[str] = None,
python="*", # type: str python: str = "*",
dependencies=None, # type: Optional[Dict[str, str]] dependencies: Optional[Dict[str, str]] = None,
dev_dependencies=None, # type: Optional[Dict[str, str]] dev_dependencies: Optional[Dict[str, str]] = None,
): ):
self._project = project self._project = project
self._package_name = module_name(project) self._package_name = module_name(project)
...@@ -78,7 +79,7 @@ class Layout(object): ...@@ -78,7 +79,7 @@ class Layout(object):
self._author = author 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) path.mkdir(parents=True, exist_ok=True)
self._create_default(path) self._create_default(path)
...@@ -90,8 +91,8 @@ class Layout(object): ...@@ -90,8 +91,8 @@ class Layout(object):
self._write_poetry(path) self._write_poetry(path)
def generate_poetry_content( def generate_poetry_content(
self, original=None self, original: Optional["PyProjectTOML"] = None
): # type: (Optional["PyProjectTOML"]) -> str ) -> str:
template = POETRY_DEFAULT template = POETRY_DEFAULT
if self._license: if self._license:
template = POETRY_WITH_LICENSE template = POETRY_WITH_LICENSE
...@@ -131,10 +132,10 @@ class Layout(object): ...@@ -131,10 +132,10 @@ class Layout(object):
return content 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() raise NotImplementedError()
def _create_readme(self, path): # type: (Path) -> None def _create_readme(self, path: "Path") -> None:
if self._readme_format == "rst": if self._readme_format == "rst":
readme_file = path / "README.rst" readme_file = path / "README.rst"
else: else:
...@@ -142,7 +143,7 @@ class Layout(object): ...@@ -142,7 +143,7 @@ class Layout(object):
readme_file.touch() readme_file.touch()
def _create_tests(self, path): # type: (Path) -> None def _create_tests(self, path: "Path") -> None:
tests = path / "tests" tests = path / "tests"
tests_init = tests / "__init__.py" tests_init = tests / "__init__.py"
tests_default = tests / "test_{}.py".format(self._package_name) tests_default = tests / "test_{}.py".format(self._package_name)
...@@ -157,7 +158,7 @@ class Layout(object): ...@@ -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() content = self.generate_poetry_content()
poetry = path / "pyproject.toml" poetry = path / "pyproject.toml"
......
...@@ -6,14 +6,14 @@ from .layout import Layout ...@@ -6,14 +6,14 @@ from .layout import Layout
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa from pathlib import Path
DEFAULT = u"""__version__ = '{version}' DEFAULT = u"""__version__ = '{version}'
""" """
class SrcLayout(Layout): 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_path = path / "src" / self._package_name
package_init = package_path / "__init__.py" package_init = package_path / "__init__.py"
......
...@@ -6,13 +6,13 @@ from .layout import Layout ...@@ -6,13 +6,13 @@ from .layout import Layout
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa from pathlib import Path
DEFAULT = u"""__version__ = '{version}' DEFAULT = u"""__version__ = '{version}'
""" """
class StandardLayout(Layout): 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_path = path / self._package_name
package_init = package_path / "__init__.py" package_init = package_path / "__init__.py"
......
...@@ -21,8 +21,8 @@ from poetry.utils.helpers import is_dir_writable ...@@ -21,8 +21,8 @@ from poetry.utils.helpers import is_dir_writable
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.io.io import IO # noqa from cleo.io.io import IO # noqa
from poetry.core.poetry import Poetry # noqa from poetry.core.poetry import Poetry
from poetry.utils.env import Env # noqa from poetry.utils.env import Env
SCRIPT_TEMPLATE = """\ SCRIPT_TEMPLATE = """\
#!{python} #!{python}
...@@ -38,13 +38,13 @@ WINDOWS_CMD_TEMPLATE = """\ ...@@ -38,13 +38,13 @@ WINDOWS_CMD_TEMPLATE = """\
class EditableBuilder(Builder): 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) super(EditableBuilder, self).__init__(poetry)
self._env = env self._env = env
self._io = io self._io = io
def build(self): # type: () -> None def build(self) -> None:
self._debug( self._debug(
" - Building package <c1>{}</c1> in <info>editable</info> mode".format( " - Building package <c1>{}</c1> in <info>editable</info> mode".format(
self._package.name self._package.name
...@@ -66,11 +66,11 @@ class EditableBuilder(Builder): ...@@ -66,11 +66,11 @@ class EditableBuilder(Builder):
added_files += self._add_scripts() added_files += self._add_scripts()
self._add_dist_info(added_files) 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._debug(" - Executing build script: <b>{}</b>".format(build_script))
self._env.run("python", str(self._path.joinpath(build_script)), call=True) 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) builder = SdistBuilder(self._poetry)
setup = self._path / "setup.py" setup = self._path / "setup.py"
has_setup = setup.exists() has_setup = setup.exists()
...@@ -102,7 +102,7 @@ class EditableBuilder(Builder): ...@@ -102,7 +102,7 @@ class EditableBuilder(Builder):
if not has_setup: if not has_setup:
os.remove(str(setup)) os.remove(str(setup))
def _add_pth(self): # type: () -> List[Path] def _add_pth(self) -> List[Path]:
paths = set() paths = set()
for include in self._module.includes: for include in self._module.includes:
if isinstance(include, PackageInclude) and ( if isinstance(include, PackageInclude) and (
...@@ -127,14 +127,14 @@ class EditableBuilder(Builder): ...@@ -127,14 +127,14 @@ class EditableBuilder(Builder):
return [pth_file] return [pth_file]
except OSError: except OSError:
# TODO: Replace with PermissionError # TODO: Replace with PermissionError
self._io.error_line( self._io.write_error_line(
" - Failed to create <c2>{}</c2> for {}".format( " - Failed to create <c2>{}</c2> for {}".format(
pth_file.name, self._poetry.file.parent pth_file.name, self._poetry.file.parent
) )
) )
return [] return []
def _add_scripts(self): # type: () -> List[Path] def _add_scripts(self) -> List[Path]:
added = [] added = []
entry_points = self.convert_entry_points() entry_points = self.convert_entry_points()
...@@ -142,7 +142,7 @@ class EditableBuilder(Builder): ...@@ -142,7 +142,7 @@ class EditableBuilder(Builder):
if is_dir_writable(path=scripts_path, create=True): if is_dir_writable(path=scripts_path, create=True):
break break
else: else:
self._io.error_line( self._io.write_error_line(
" - Failed to find a suitable script installation directory for {}".format( " - Failed to find a suitable script installation directory for {}".format(
self._poetry.file.parent self._poetry.file.parent
) )
...@@ -193,7 +193,7 @@ class EditableBuilder(Builder): ...@@ -193,7 +193,7 @@ class EditableBuilder(Builder):
return added 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 from poetry.core.masonry.builders.wheel import WheelBuilder
added_files = added_files[:] added_files = added_files[:]
...@@ -247,7 +247,7 @@ class EditableBuilder(Builder): ...@@ -247,7 +247,7 @@ class EditableBuilder(Builder):
# RECORD itself is recorded with no hash or size # RECORD itself is recorded with no hash or size
f.write("{},,\n".format(dist_info.joinpath("RECORD"))) 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() hashsum = hashlib.sha256()
with filepath.open("rb") as src: with filepath.open("rb") as src:
while True: while True:
...@@ -260,6 +260,6 @@ class EditableBuilder(Builder): ...@@ -260,6 +260,6 @@ class EditableBuilder(Builder):
return urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") 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(): if self._io.is_debug():
self._io.write_line(msg) self._io.write_line(msg)
...@@ -6,16 +6,19 @@ from .version_solver import VersionSolver ...@@ -6,16 +6,19 @@ from .version_solver import VersionSolver
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import DependencyPackage # noqa from poetry.core.packages import ProjectPackage
from poetry.core.packages import ProjectPackage # noqa from poetry.packages import DependencyPackage
from poetry.puzzle.provider import Provider # noqa from poetry.puzzle.provider import Provider
from .result import SolverResult # noqa from .result import SolverResult
def resolve_version( def resolve_version(
root, provider, locked=None, use_latest=None root: "ProjectPackage",
): # type: ("ProjectPackage", "Provider", Dict[str, "DependencyPackage"],List[str]) -> "SolverResult" provider: "Provider",
locked: Dict[str, "DependencyPackage"] = None,
use_latest: List[str] = None,
) -> "SolverResult":
solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest) solver = VersionSolver(root, provider, locked=locked, use_latest=use_latest)
return solver.solve() return solver.solve()
...@@ -6,10 +6,10 @@ from .term import Term ...@@ -6,10 +6,10 @@ from .term import Term
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
from .incompatibility import Incompatibility # noqa from .incompatibility import Incompatibility
class Assignment(Term): class Assignment(Term):
...@@ -18,8 +18,13 @@ class Assignment(Term): ...@@ -18,8 +18,13 @@ class Assignment(Term):
""" """
def __init__( def __init__(
self, dependency, is_positive, decision_level, index, cause=None self,
): # type: ("Dependency", bool, int, int, Optional["Incompatibility"]) -> None dependency: "Dependency",
is_positive: bool,
decision_level: int,
index: int,
cause: Optional["Incompatibility"] = None,
) -> None:
super(Assignment, self).__init__(dependency, is_positive) super(Assignment, self).__init__(dependency, is_positive)
self._decision_level = decision_level self._decision_level = decision_level
...@@ -27,28 +32,33 @@ class Assignment(Term): ...@@ -27,28 +32,33 @@ class Assignment(Term):
self._cause = cause self._cause = cause
@property @property
def decision_level(self): # type: () -> int def decision_level(self) -> int:
return self._decision_level return self._decision_level
@property @property
def index(self): # type: () -> int def index(self) -> int:
return self._index return self._index
@property @property
def cause(self): # type: () -> "Incompatibility" def cause(self) -> "Incompatibility":
return self._cause return self._cause
@classmethod @classmethod
def decision( def decision(
cls, package, decision_level, index cls, package: "Package", decision_level: int, index: int
): # type: ("Package", int, int) -> Assignment ) -> "Assignment":
return cls(package.to_dependency(), True, decision_level, index) return cls(package.to_dependency(), True, decision_level, index)
@classmethod @classmethod
def derivation( def derivation(
cls, dependency, is_positive, cause, decision_level, index cls,
): # type: (Any, bool, "Incompatibility", int, int) -> "Assignment" dependency: Any,
is_positive: bool,
cause: "Incompatibility",
decision_level: int,
index: int,
) -> "Assignment":
return cls(dependency, is_positive, decision_level, index, cause) 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 return self._cause is None
...@@ -11,27 +11,27 @@ from .incompatibility_cause import PythonCause ...@@ -11,27 +11,27 @@ from .incompatibility_cause import PythonCause
class SolveFailure(Exception): class SolveFailure(Exception):
def __init__(self, incompatibility): # type: (Incompatibility) -> None def __init__(self, incompatibility: Incompatibility) -> None:
self._incompatibility = incompatibility self._incompatibility = incompatibility
@property @property
def message(self): # type: () -> str def message(self) -> str:
return str(self) return str(self)
def __str__(self): # type: () -> str def __str__(self) -> str:
return _Writer(self._incompatibility).write() return _Writer(self._incompatibility).write()
class _Writer: class _Writer:
def __init__(self, root): # type: (Incompatibility) -> None def __init__(self, root: Incompatibility) -> None:
self._root = root self._root = root
self._derivations = {} # type: Dict[Incompatibility, int] self._derivations: Dict[Incompatibility, int] = {}
self._lines = [] # type: List[Tuple[str, Optional[int]]] self._lines: List[Tuple[str, Optional[int]]] = []
self._line_numbers = {} # type: Dict[Incompatibility, int] self._line_numbers: Dict[Incompatibility, int] = {}
self._count_derivations(self._root) self._count_derivations(self._root)
def write(self): # type: () -> str def write(self) -> str:
buffer = [] buffer = []
required_python_version_notification = False required_python_version_notification = False
...@@ -98,8 +98,8 @@ class _Writer: ...@@ -98,8 +98,8 @@ class _Writer:
return "\n".join(buffer) return "\n".join(buffer)
def _write( def _write(
self, incompatibility, message, numbered=False self, incompatibility: Incompatibility, message: str, numbered: bool = False
): # type: (Incompatibility, str, bool) -> None ) -> None:
if numbered: if numbered:
number = len(self._line_numbers) + 1 number = len(self._line_numbers) + 1
self._line_numbers[incompatibility] = number self._line_numbers[incompatibility] = number
...@@ -108,8 +108,11 @@ class _Writer: ...@@ -108,8 +108,11 @@ class _Writer:
self._lines.append((message, None)) self._lines.append((message, None))
def _visit( def _visit(
self, incompatibility, details_for_incompatibility, conclusion=False self,
): # type: (Incompatibility, Dict, bool) -> None incompatibility: Incompatibility,
details_for_incompatibility: Dict,
conclusion: bool = False,
) -> None:
numbered = conclusion or self._derivations[incompatibility] > 1 numbered = conclusion or self._derivations[incompatibility] > 1
conjunction = "So," if conclusion or incompatibility == self._root else "And" conjunction = "So," if conclusion or incompatibility == self._root else "And"
incompatibility_string = str(incompatibility) incompatibility_string = str(incompatibility)
...@@ -208,7 +211,7 @@ class _Writer: ...@@ -208,7 +211,7 @@ class _Writer:
numbered=numbered, numbered=numbered,
) )
elif self._is_collapsible(derived): elif self._is_collapsible(derived):
derived_cause = derived.cause # type: ConflictCause derived_cause: ConflictCause = derived.cause
if isinstance(derived_cause.conflict.cause, ConflictCause): if isinstance(derived_cause.conflict.cause, ConflictCause):
collapsed_derived = derived_cause.conflict collapsed_derived = derived_cause.conflict
else: else:
...@@ -252,11 +255,11 @@ class _Writer: ...@@ -252,11 +255,11 @@ class _Writer:
numbered=numbered, numbered=numbered,
) )
def _is_collapsible(self, incompatibility): # type: (Incompatibility) -> bool def _is_collapsible(self, incompatibility: Incompatibility) -> bool:
if self._derivations[incompatibility] > 1: if self._derivations[incompatibility] > 1:
return False return False
cause = incompatibility.cause # type: ConflictCause cause: ConflictCause = incompatibility.cause
if isinstance(cause.conflict.cause, ConflictCause) and isinstance( if isinstance(cause.conflict.cause, ConflictCause) and isinstance(
cause.other.cause, ConflictCause cause.other.cause, ConflictCause
): ):
...@@ -275,12 +278,12 @@ class _Writer: ...@@ -275,12 +278,12 @@ class _Writer:
return complex not in self._line_numbers 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( return not isinstance(cause.conflict.cause, ConflictCause) and not isinstance(
cause.other.cause, ConflictCause cause.other.cause, ConflictCause
) )
def _count_derivations(self, incompatibility): # type: (Incompatibility) -> None def _count_derivations(self, incompatibility: Incompatibility) -> None:
if incompatibility in self._derivations: if incompatibility in self._derivations:
self._derivations[incompatibility] += 1 self._derivations[incompatibility] += 1
else: else:
......
from typing import Dict from typing import Dict
from typing import Generator from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Union from typing import Union
...@@ -16,9 +16,7 @@ from .term import Term ...@@ -16,9 +16,7 @@ from .term import Term
class Incompatibility: class Incompatibility:
def __init__( def __init__(self, terms: List[Term], cause: IncompatibilityCause) -> None:
self, terms, cause
): # type: (List[Term], IncompatibilityCause) -> None
# Remove the root package from generated incompatibilities, since it will # Remove the root package from generated incompatibilities, since it will
# always be satisfied. This makes error reporting clearer, and may also # always be satisfied. This makes error reporting clearer, and may also
# make solving more efficient. # make solving more efficient.
...@@ -43,7 +41,7 @@ class Incompatibility: ...@@ -43,7 +41,7 @@ class Incompatibility:
pass pass
else: else:
# Coalesce multiple terms about the same package if possible. # 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: for term in terms:
if term.dependency.complete_name not in by_name: if term.dependency.complete_name not in by_name:
by_name[term.dependency.complete_name] = {} by_name[term.dependency.complete_name] = {}
...@@ -80,25 +78,33 @@ class Incompatibility: ...@@ -80,25 +78,33 @@ class Incompatibility:
self._cause = cause self._cause = cause
@property @property
def terms(self): # type: () -> List[Term] def terms(self) -> List[Term]:
return self._terms return self._terms
@property @property
def cause( def cause(
self, self,
): # type: () -> Union[RootCause, NoVersionsCause, DependencyCause, ConflictCause, PythonCause, PlatformCause, PackageNotFoundCause] ) -> Union[
RootCause,
NoVersionsCause,
DependencyCause,
ConflictCause,
PythonCause,
PlatformCause,
PackageNotFoundCause,
]:
return self._cause return self._cause
@property @property
def external_incompatibilities( def external_incompatibilities(
self, self,
): # type: () -> Generator[Union[ConflictCause, Incompatibility]] ) -> Iterator[Union[ConflictCause, "Incompatibility"]]:
""" """
Returns all external incompatibilities in this incompatibility's Returns all external incompatibilities in this incompatibility's
derivation graph. derivation graph.
""" """
if isinstance(self._cause, ConflictCause): if isinstance(self._cause, ConflictCause):
cause = self._cause # type: ConflictCause cause: ConflictCause = self._cause
for incompatibility in cause.conflict.external_incompatibilities: for incompatibility in cause.conflict.external_incompatibilities:
yield incompatibility yield incompatibility
...@@ -107,12 +113,12 @@ class Incompatibility: ...@@ -107,12 +113,12 @@ class Incompatibility:
else: else:
yield self yield self
def is_failure(self): # type: () -> bool def is_failure(self) -> bool:
return len(self._terms) == 0 or ( return len(self._terms) == 0 or (
len(self._terms) == 1 and self._terms[0].dependency.is_root 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): if isinstance(self._cause, DependencyCause):
assert len(self._terms) == 2 assert len(self._terms) == 2
...@@ -128,7 +134,7 @@ class Incompatibility: ...@@ -128,7 +134,7 @@ class Incompatibility:
assert len(self._terms) == 1 assert len(self._terms) == 1
assert self._terms[0].is_positive() 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 = "{} requires ".format(self._terse(self._terms[0], allow_every=True))
text += "Python {}".format(cause.python_version) text += "Python {}".format(cause.python_version)
...@@ -137,7 +143,7 @@ class Incompatibility: ...@@ -137,7 +143,7 @@ class Incompatibility:
assert len(self._terms) == 1 assert len(self._terms) == 1
assert self._terms[0].is_positive() 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 = "{} requires ".format(self._terse(self._terms[0], allow_every=True))
text += "platform {}".format(cause.platform) text += "platform {}".format(cause.platform)
...@@ -227,8 +233,12 @@ class Incompatibility: ...@@ -227,8 +233,12 @@ class Incompatibility:
return "one of {} must be true".format(" or ".join(negative)) return "one of {} must be true".format(" or ".join(negative))
def and_to_string( def and_to_string(
self, other, details, this_line, other_line self,
): # type: (Incompatibility, dict, Optional[int], Optional[int]) -> str 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) requires_both = self._try_requires_both(other, details, this_line, other_line)
if requires_both is not None: if requires_both is not None:
return requires_both return requires_both
...@@ -257,8 +267,12 @@ class Incompatibility: ...@@ -257,8 +267,12 @@ class Incompatibility:
return "\n".join(buffer) return "\n".join(buffer)
def _try_requires_both( def _try_requires_both(
self, other, details, this_line, other_line self,
): # type: (Incompatibility, dict, Optional[int], Optional[int]) -> Optional[str] other: "Incompatibility",
details: dict,
this_line: Optional[int],
other_line: Optional[int],
) -> Optional[str]:
if len(self._terms) == 1 or len(other.terms) == 1: if len(self._terms) == 1 or len(other.terms) == 1:
return return
...@@ -303,8 +317,8 @@ class Incompatibility: ...@@ -303,8 +317,8 @@ class Incompatibility:
return "".join(buffer) return "".join(buffer)
def _try_requires_through( def _try_requires_through(
self, other, details, this_line, other_line self, other: "Incompatibility", details: dict, this_line: int, other_line: int
): # type: (Incompatibility, dict, int, int) -> Optional[str] ) -> Optional[str]:
if len(self._terms) == 1 or len(other.terms) == 1: if len(self._terms) == 1 or len(other.terms) == 1:
return return
...@@ -381,8 +395,8 @@ class Incompatibility: ...@@ -381,8 +395,8 @@ class Incompatibility:
return "".join(buffer) return "".join(buffer)
def _try_requires_forbidden( def _try_requires_forbidden(
self, other, details, this_line, other_line self, other: "Incompatibility", details: dict, this_line: int, other_line: int
): # type: (Incompatibility, dict, int, int) -> Optional[str] ) -> Optional[str]:
if len(self._terms) != 1 and len(other.terms) != 1: if len(self._terms) != 1 and len(other.terms) != 1:
return None return None
...@@ -422,7 +436,7 @@ class Incompatibility: ...@@ -422,7 +436,7 @@ class Incompatibility:
buffer.append("({}) ".format(prior_line)) buffer.append("({}) ".format(prior_line))
if isinstance(latter.cause, PythonCause): if isinstance(latter.cause, PythonCause):
cause = latter.cause # type: PythonCause cause: PythonCause = latter.cause
buffer.append("which requires Python {}".format(cause.python_version)) buffer.append("which requires Python {}".format(cause.python_version))
elif isinstance(latter.cause, NoVersionsCause): elif isinstance(latter.cause, NoVersionsCause):
buffer.append("which doesn't match any versions") buffer.append("which doesn't match any versions")
...@@ -436,13 +450,13 @@ class Incompatibility: ...@@ -436,13 +450,13 @@ class Incompatibility:
return "".join(buffer) 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(): if allow_every and term.constraint.is_any():
return "every version of {}".format(term.dependency.complete_name) return "every version of {}".format(term.dependency.complete_name)
return str(term.dependency) 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 found = None
for term in self._terms: for term in self._terms:
if not callable(term): if not callable(term):
...@@ -455,5 +469,5 @@ class Incompatibility: ...@@ -455,5 +469,5 @@ class Incompatibility:
return found return found
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return "<Incompatibility {}>".format(str(self)) return "<Incompatibility {}>".format(str(self))
...@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING ...@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.mixology.incompatibility import Incompatibility # noqa from poetry.mixology.incompatibility import Incompatibility
class IncompatibilityCause(Exception): class IncompatibilityCause(Exception):
...@@ -32,21 +32,19 @@ class ConflictCause(IncompatibilityCause): ...@@ -32,21 +32,19 @@ class ConflictCause(IncompatibilityCause):
during conflict resolution. during conflict resolution.
""" """
def __init__( def __init__(self, conflict: "Incompatibility", other: "Incompatibility") -> None:
self, conflict, other
): # type: ("Incompatibility", "Incompatibility") -> None
self._conflict = conflict self._conflict = conflict
self._other = other self._other = other
@property @property
def conflict(self): # type: () -> "Incompatibility" def conflict(self) -> "Incompatibility":
return self._conflict return self._conflict
@property @property
def other(self): # type: () -> "Incompatibility" def other(self) -> "Incompatibility":
return self._other return self._other
def __str__(self): # type: () -> str def __str__(self) -> str:
return str(self._conflict) return str(self._conflict)
...@@ -57,16 +55,16 @@ class PythonCause(IncompatibilityCause): ...@@ -57,16 +55,16 @@ class PythonCause(IncompatibilityCause):
with the current python version. 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._python_version = python_version
self._root_python_version = root_python_version self._root_python_version = root_python_version
@property @property
def python_version(self): # type: () -> str def python_version(self) -> str:
return self._python_version return self._python_version
@property @property
def root_python_version(self): # type: () -> str def root_python_version(self) -> str:
return self._root_python_version return self._root_python_version
...@@ -76,11 +74,11 @@ class PlatformCause(IncompatibilityCause): ...@@ -76,11 +74,11 @@ class PlatformCause(IncompatibilityCause):
(OS most likely) being incompatible with the current platform. (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 self._platform = platform
@property @property
def platform(self): # type: () -> str def platform(self) -> str:
return self._platform return self._platform
...@@ -90,9 +88,9 @@ class PackageNotFoundCause(IncompatibilityCause): ...@@ -90,9 +88,9 @@ class PackageNotFoundCause(IncompatibilityCause):
source. source.
""" """
def __init__(self, error): # type: (Exception) -> None def __init__(self, error: Exception) -> None:
self._error = error self._error = error
@property @property
def error(self): # type: () -> Exception def error(self) -> Exception:
return self._error return self._error
...@@ -9,9 +9,8 @@ from .term import Term ...@@ -9,9 +9,8 @@ from .term import Term
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
from poetry.packages import DependencyPackage # noqa
class PartialSolution: class PartialSolution:
...@@ -23,19 +22,19 @@ class PartialSolution: ...@@ -23,19 +22,19 @@ class PartialSolution:
# See https://github.com/dart-lang/mixology/tree/master/doc/solver.md#partial-solution. # 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 # The assignments that have been made so far, in the order they were
# assigned. # assigned.
self._assignments = [] # type: List[Assignment] self._assignments: List[Assignment] = []
# The decisions made for each package. # 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 # The intersection of all positive Assignments for each package, minus any
# negative Assignments that refer to that package. # negative Assignments that refer to that package.
# #
# This is derived from self._assignments. # 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. # The union of all negative Assignments for each package.
# #
...@@ -43,7 +42,7 @@ class PartialSolution: ...@@ -43,7 +42,7 @@ class PartialSolution:
# map. # map.
# #
# This is derived from self._assignments. # 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. # The number of distinct solutions that have been attempted so far.
self._attempted_solutions = 1 self._attempted_solutions = 1
...@@ -52,26 +51,26 @@ class PartialSolution: ...@@ -52,26 +51,26 @@ class PartialSolution:
self._backtracking = False self._backtracking = False
@property @property
def decisions(self): # type: () -> List["Package"] def decisions(self) -> List["Package"]:
return list(self._decisions.values()) return list(self._decisions.values())
@property @property
def decision_level(self): # type: () -> int def decision_level(self) -> int:
return len(self._decisions) return len(self._decisions)
@property @property
def attempted_solutions(self): # type: () -> int def attempted_solutions(self) -> int:
return self._attempted_solutions return self._attempted_solutions
@property @property
def unsatisfied(self): # type: () -> List["Dependency"] def unsatisfied(self) -> List["Dependency"]:
return [ return [
term.dependency term.dependency
for term in self._positive.values() for term in self._positive.values()
if term.dependency.complete_name not in self._decisions 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 Adds an assignment of package as a decision
and increments the decision level. and increments the decision level.
...@@ -91,8 +90,8 @@ class PartialSolution: ...@@ -91,8 +90,8 @@ class PartialSolution:
) )
def derive( def derive(
self, dependency, is_positive, cause self, dependency: "Dependency", is_positive: bool, cause: Incompatibility
): # type: ("Dependency", bool, Incompatibility) -> None ) -> None:
""" """
Adds an assignment of package as a derivation. Adds an assignment of package as a derivation.
""" """
...@@ -106,14 +105,14 @@ class PartialSolution: ...@@ -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. Adds an Assignment to _assignments and _positive or _negative.
""" """
self._assignments.append(assignment) self._assignments.append(assignment)
self._register(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 Resets the current decision level to decision_level, and removes all
assignments made after that level. assignments made after that level.
...@@ -139,7 +138,7 @@ class PartialSolution: ...@@ -139,7 +138,7 @@ class PartialSolution:
if assignment.dependency.complete_name in packages: if assignment.dependency.complete_name in packages:
self._register(assignment) self._register(assignment)
def _register(self, assignment): # type: (Assignment) -> None def _register(self, assignment: Assignment) -> None:
""" """
Registers an Assignment in _positive or _negative. Registers an Assignment in _positive or _negative.
""" """
...@@ -169,7 +168,7 @@ class PartialSolution: ...@@ -169,7 +168,7 @@ class PartialSolution:
self._negative[name][ref] = term 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 Returns the first Assignment in this solution such that the sublist of
assignments up to and including that entry collectively satisfies term. assignments up to and including that entry collectively satisfies term.
...@@ -202,10 +201,10 @@ class PartialSolution: ...@@ -202,10 +201,10 @@ class PartialSolution:
raise RuntimeError("[BUG] {} is not satisfied.".format(term)) 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 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) positive = self._positive.get(term.dependency.complete_name)
if positive is not None: if positive is not None:
return positive.relation(term) return positive.relation(term)
......
...@@ -3,22 +3,25 @@ from typing import List ...@@ -3,22 +3,25 @@ from typing import List
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
from poetry.core.packages import ProjectPackage # noqa from poetry.core.packages import ProjectPackage
class SolverResult: class SolverResult:
def __init__( def __init__(
self, root, packages, attempted_solutions self,
): # type: ("ProjectPackage", List["Package"], int) -> None root: "ProjectPackage",
packages: List["Package"],
attempted_solutions: int,
) -> None:
self._root = root self._root = root
self._packages = packages self._packages = packages
self._attempted_solutions = attempted_solutions self._attempted_solutions = attempted_solutions
@property @property
def packages(self): # type: () -> List["Package"] def packages(self) -> List["Package"]:
return self._packages return self._packages
@property @property
def attempted_solutions(self): # type: () -> int def attempted_solutions(self) -> int:
return self._attempted_solutions return self._attempted_solutions
...@@ -7,7 +7,7 @@ from crashtest.contracts.solution import Solution ...@@ -7,7 +7,7 @@ from crashtest.contracts.solution import Solution
class PythonRequirementSolutionProvider(HasSolutionsForException): class PythonRequirementSolutionProvider(HasSolutionsForException):
def can_solve(self, exception): # type: (Exception) -> bool def can_solve(self, exception: Exception) -> bool:
from poetry.puzzle.exceptions import SolverProblemError from poetry.puzzle.exceptions import SolverProblemError
if not isinstance(exception, SolverProblemError): if not isinstance(exception, SolverProblemError):
...@@ -24,7 +24,7 @@ class PythonRequirementSolutionProvider(HasSolutionsForException): ...@@ -24,7 +24,7 @@ class PythonRequirementSolutionProvider(HasSolutionsForException):
return True 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 from ..solutions.python_requirement_solution import PythonRequirementSolution
return [PythonRequirementSolution(exception)] return [PythonRequirementSolution(exception)]
...@@ -5,11 +5,11 @@ from crashtest.contracts.solution import Solution ...@@ -5,11 +5,11 @@ from crashtest.contracts.solution import Solution
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.mixology.incompatibility_cause import PackageNotFoundCause # noqa from poetry.mixology.incompatibility_cause import PackageNotFoundCause
class PythonRequirementSolution(Solution): 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.core.semver import parse_constraint
from poetry.mixology.incompatibility_cause import PythonCause from poetry.mixology.incompatibility_cause import PythonCause
...@@ -44,15 +44,15 @@ class PythonRequirementSolution(Solution): ...@@ -44,15 +44,15 @@ class PythonRequirementSolution(Solution):
self._description = description self._description = description
@property @property
def solution_title(self): # type: () -> str def solution_title(self) -> str:
return self._title return self._title
@property @property
def solution_description(self): # type: () -> str def solution_description(self) -> str:
return self._description return self._description
@property @property
def documentation_links(self): # type: () -> List[str] def documentation_links(self) -> List[str]:
return [ return [
"https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies", "https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies",
"https://python-poetry.org/docs/dependency-specification/#using-environment-markers", "https://python-poetry.org/docs/dependency-specification/#using-environment-markers",
......
...@@ -8,7 +8,7 @@ from .set_relation import SetRelation ...@@ -8,7 +8,7 @@ from .set_relation import SetRelation
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.semver import VersionTypes # noqa from poetry.core.semver import VersionTypes
class Term(object): class Term(object):
...@@ -19,26 +19,26 @@ class Term(object): ...@@ -19,26 +19,26 @@ class Term(object):
See https://github.com/dart-lang/pub/tree/master/doc/solver.md#term. 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._dependency = dependency
self._positive = is_positive self._positive = is_positive
@property @property
def inverse(self): # type: () -> Term def inverse(self) -> "Term":
return Term(self._dependency, not self.is_positive()) return Term(self._dependency, not self.is_positive())
@property @property
def dependency(self): # type: () -> Dependency def dependency(self) -> Dependency:
return self._dependency return self._dependency
@property @property
def constraint(self): # type: () -> "VersionTypes" def constraint(self) -> "VersionTypes":
return self._dependency.constraint return self._dependency.constraint
def is_positive(self): # type: () -> bool def is_positive(self) -> bool:
return self._positive return self._positive
def satisfies(self, other): # type: (Term) -> bool def satisfies(self, other: "Term") -> bool:
""" """
Returns whether this term satisfies another. Returns whether this term satisfies another.
""" """
...@@ -47,7 +47,7 @@ class Term(object): ...@@ -47,7 +47,7 @@ class Term(object):
and self.relation(other) == SetRelation.SUBSET 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 Returns the relationship between the package versions
allowed by this term and another. allowed by this term and another.
...@@ -111,7 +111,7 @@ class Term(object): ...@@ -111,7 +111,7 @@ class Term(object):
# not foo ^1.5.0 is a superset of not foo ^1.0.0 # not foo ^1.5.0 is a superset of not foo ^1.0.0
return SetRelation.OVERLAPPING 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 Returns a Term that represents the packages
allowed by both this term and another allowed by both this term and another
...@@ -145,14 +145,14 @@ class Term(object): ...@@ -145,14 +145,14 @@ class Term(object):
else: else:
return return
def difference(self, other): # type: (Term) -> Term def difference(self, other: "Term") -> "Term":
""" """
Returns a Term that represents packages Returns a Term that represents packages
allowed by this term and not by the other allowed by this term and not by the other
""" """
return self.intersect(other.inverse) return self.intersect(other.inverse)
def _compatible_dependency(self, other): # type: (Term) -> bool def _compatible_dependency(self, other: "Dependency") -> bool:
return ( return (
self.dependency.is_root self.dependency.is_root
or other.is_root or other.is_root
...@@ -160,15 +160,15 @@ class Term(object): ...@@ -160,15 +160,15 @@ class Term(object):
) )
def _non_empty_term( def _non_empty_term(
self, constraint, is_positive self, constraint: "VersionTypes", is_positive: bool
): # type: ("VersionTypes", bool) -> Optional[Term] ) -> Optional["Term"]:
if constraint.is_empty(): if constraint.is_empty():
return return
return Term(self.dependency.with_constraint(constraint), is_positive) 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) 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)) return "<Term {}>".format(str(self))
...@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING ...@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Union
from poetry.core.packages import Dependency from poetry.core.packages import Dependency
from poetry.core.packages import Package from poetry.core.packages import Package
...@@ -40,10 +41,10 @@ class VersionSolver: ...@@ -40,10 +41,10 @@ class VersionSolver:
def __init__( def __init__(
self, self,
root, # type: ProjectPackage root: ProjectPackage,
provider, # type: Provider provider: "Provider",
locked=None, # type: Dict[str, Package] locked: Dict[str, Package] = None,
use_latest=None, # type: List[str] use_latest: List[str] = None,
): ):
self._root = root self._root = root
self._provider = provider self._provider = provider
...@@ -54,14 +55,14 @@ class VersionSolver: ...@@ -54,14 +55,14 @@ class VersionSolver:
self._use_latest = use_latest self._use_latest = use_latest
self._incompatibilities = {} # type: Dict[str, List[Incompatibility]] self._incompatibilities: Dict[str, List[Incompatibility]] = {}
self._solution = PartialSolution() self._solution = PartialSolution()
@property @property
def solution(self): # type: () -> PartialSolution def solution(self) -> PartialSolution:
return self._solution return self._solution
def solve(self): # type: () -> SolverResult def solve(self) -> SolverResult:
""" """
Finds a set of dependencies that match the root package's constraints, Finds a set of dependencies that match the root package's constraints,
or raises an error if no such set is available. or raises an error if no such set is available.
...@@ -91,7 +92,7 @@ class VersionSolver: ...@@ -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 Performs unit propagation on incompatibilities transitively
related to package to derive new assignments for _solution. related to package to derive new assignments for _solution.
...@@ -129,8 +130,8 @@ class VersionSolver: ...@@ -129,8 +130,8 @@ class VersionSolver:
changed.add(result) changed.add(result)
def _propagate_incompatibility( def _propagate_incompatibility(
self, incompatibility self, incompatibility: Incompatibility
): # type: (Incompatibility) -> Optional[str, _conflict] ) -> Optional[Union[str, object]]:
""" """
If incompatibility is almost satisfied by _solution, adds the If incompatibility is almost satisfied by _solution, adds the
negation of the unsatisfied term to _solution. negation of the unsatisfied term to _solution.
...@@ -182,9 +183,7 @@ class VersionSolver: ...@@ -182,9 +183,7 @@ class VersionSolver:
return unsatisfied.dependency.complete_name return unsatisfied.dependency.complete_name
def _resolve_conflict( def _resolve_conflict(self, incompatibility: Incompatibility) -> Incompatibility:
self, incompatibility
): # type: (Incompatibility) -> Incompatibility
""" """
Given an incompatibility that's satisfied by _solution, Given an incompatibility that's satisfied by _solution,
The `conflict resolution`_ constructs a new incompatibility that encapsulates the root The `conflict resolution`_ constructs a new incompatibility that encapsulates the root
...@@ -317,7 +316,7 @@ class VersionSolver: ...@@ -317,7 +316,7 @@ class VersionSolver:
raise SolveFailure(incompatibility) 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. Tries to select a version of a required package.
...@@ -331,7 +330,7 @@ class VersionSolver: ...@@ -331,7 +330,7 @@ class VersionSolver:
# Prefer packages with as few remaining versions as possible, # Prefer packages with as few remaining versions as possible,
# so that if a conflict is necessary it's forced quickly. # 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 dependency.name in self._use_latest:
# If we're forced to use the latest version of a package, it effectively # If we're forced to use the latest version of a package, it effectively
# only has one version to choose from. # only has one version to choose from.
...@@ -418,7 +417,7 @@ class VersionSolver: ...@@ -418,7 +417,7 @@ class VersionSolver:
return dependency.complete_name return dependency.complete_name
def _result(self): # type: () -> SolverResult def _result(self) -> SolverResult:
""" """
Creates a #SolverResult from the decisions in _solution Creates a #SolverResult from the decisions in _solution
""" """
...@@ -430,7 +429,7 @@ class VersionSolver: ...@@ -430,7 +429,7 @@ class VersionSolver:
self._solution.attempted_solutions, self._solution.attempted_solutions,
) )
def _add_incompatibility(self, incompatibility): # type: (Incompatibility) -> None def _add_incompatibility(self, incompatibility: Incompatibility) -> None:
self._log("fact: {}".format(incompatibility)) self._log("fact: {}".format(incompatibility))
for term in incompatibility.terms: for term in incompatibility.terms:
...@@ -447,7 +446,7 @@ class VersionSolver: ...@@ -447,7 +446,7 @@ class VersionSolver:
incompatibility 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: if dependency.name in self._use_latest:
return return
...@@ -460,5 +459,5 @@ class VersionSolver: ...@@ -460,5 +459,5 @@ class VersionSolver:
return locked return locked
def _log(self, text): # type: (str) -> None def _log(self, text: str) -> None:
self._provider.debug(text, self._solution.attempted_solutions) self._provider.debug(text, self._solution.attempted_solutions)
...@@ -7,46 +7,46 @@ from poetry.core.packages.package import Package ...@@ -7,46 +7,46 @@ from poetry.core.packages.package import Package
class DependencyPackage(object): class DependencyPackage(object):
def __init__(self, dependency, package): # type: (Dependency, Package) -> None def __init__(self, dependency: Dependency, package: Package) -> None:
self._dependency = dependency self._dependency = dependency
self._package = package self._package = package
@property @property
def dependency(self): # type: () -> Dependency def dependency(self) -> Dependency:
return self._dependency return self._dependency
@property @property
def package(self): # type: () -> Package def package(self) -> Package:
return self._package return self._package
def clone(self): # type: () -> "DependencyPackage" def clone(self) -> "DependencyPackage":
return self.__class__(self._dependency, self._package.clone()) 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)) 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([]) return self.with_features([])
def __getattr__(self, name): # type: (str) -> Any def __getattr__(self, name: str) -> Any:
return getattr(self._package, name) 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"}: if key in {"_dependency", "_package"}:
return super(DependencyPackage, self).__setattr__(key, value) return super(DependencyPackage, self).__setattr__(key, value)
setattr(self._package, key, value) setattr(self._package, key, value)
def __str__(self): # type: () -> str def __str__(self) -> str:
return str(self._package) return str(self._package)
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return repr(self._package) return repr(self._package)
def __hash__(self): # type: () -> int def __hash__(self) -> int:
return hash(self._package) 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): if isinstance(other, DependencyPackage):
other = other.package other = other.package
......
...@@ -39,7 +39,7 @@ from poetry.utils.extras import get_extra_package_names ...@@ -39,7 +39,7 @@ from poetry.utils.extras import get_extra_package_names
if TYPE_CHECKING: if TYPE_CHECKING:
from ptomlkit.toml_document import TOMLDocument # noqa from tomlkit.toml_document import TOMLDocument
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -50,24 +50,24 @@ class Locker(object): ...@@ -50,24 +50,24 @@ class Locker(object):
_relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"] _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._lock = TOMLFile(lock)
self._local_config = local_config self._local_config = local_config
self._lock_data = None self._lock_data = None
self._content_hash = self._get_content_hash() self._content_hash = self._get_content_hash()
@property @property
def lock(self): # type: () -> TOMLFile def lock(self) -> TOMLFile:
return self._lock return self._lock
@property @property
def lock_data(self): # type: () -> TOMLDocument def lock_data(self) -> "TOMLDocument":
if self._lock_data is None: if self._lock_data is None:
self._lock_data = self._get_lock_data() self._lock_data = self._get_lock_data()
return self._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). Checks whether the locker has been locked (lockfile found).
""" """
...@@ -76,7 +76,7 @@ class Locker(object): ...@@ -76,7 +76,7 @@ class Locker(object):
return "package" in self.lock_data 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. Checks whether the lock file is still up to date with the current hash.
""" """
...@@ -89,8 +89,8 @@ class Locker(object): ...@@ -89,8 +89,8 @@ class Locker(object):
return False return False
def locked_repository( def locked_repository(
self, with_dev_reqs=False self, with_dev_reqs: bool = False
): # type: (bool) -> poetry.repositories.Repository ) -> poetry.repositories.Repository:
""" """
Searches and returns a repository of locked packages. Searches and returns a repository of locked packages.
""" """
...@@ -202,8 +202,8 @@ class Locker(object): ...@@ -202,8 +202,8 @@ class Locker(object):
@staticmethod @staticmethod
def __get_locked_package( def __get_locked_package(
_dependency, packages_by_name _dependency: Dependency, packages_by_name: Dict[str, List[Package]]
): # type: (Dependency, Dict[str, List[Package]]) -> Optional[Package] ) -> Optional[Package]:
""" """
Internal helper to identify corresponding locked package using dependency Internal helper to identify corresponding locked package using dependency
version constraints. version constraints.
...@@ -216,13 +216,13 @@ class Locker(object): ...@@ -216,13 +216,13 @@ class Locker(object):
@classmethod @classmethod
def __walk_dependency_level( def __walk_dependency_level(
cls, cls,
dependencies, dependencies: List[Dependency],
level, level: int,
pinned_versions, pinned_versions: bool,
packages_by_name, packages_by_name: Dict[str, List[Package]],
project_level_dependencies, project_level_dependencies: Set[str],
nested_dependencies, nested_dependencies: Dict[Tuple[str, str], Dependency],
): # type: (List[Dependency], int, bool, Dict[str, List[Package]], Set[str], Dict[Tuple[str, str], Dependency]) -> Dict[Tuple[str, str], Dependency] ) -> Dict[Tuple[str, str], Dependency]:
if not dependencies: if not dependencies:
return nested_dependencies return nested_dependencies
...@@ -284,8 +284,12 @@ class Locker(object): ...@@ -284,8 +284,12 @@ class Locker(object):
@classmethod @classmethod
def get_project_dependencies( def get_project_dependencies(
cls, project_requires, locked_packages, pinned_versions=False, with_nested=False cls,
): # type: (List[Dependency], List[Package], bool, bool) -> Iterable[Dependency] 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 # group packages entries by name, this is required because requirement might use different constraints
packages_by_name = {} packages_by_name = {}
for pkg in locked_packages: for pkg in locked_packages:
...@@ -339,8 +343,11 @@ class Locker(object): ...@@ -339,8 +343,11 @@ class Locker(object):
return sorted(nested_dependencies.values(), key=lambda x: x.name.lower()) return sorted(nested_dependencies.values(), key=lambda x: x.name.lower())
def get_project_dependency_packages( def get_project_dependency_packages(
self, project_requires, dev=False, extras=None self,
): # type: (List[Dependency], bool, Optional[Union[bool, Sequence[str]]]) -> Iterator[DependencyPackage] project_requires: List[Dependency],
dev: bool = False,
extras: Optional[Union[bool, Sequence[str]]] = None,
) -> Iterator[DependencyPackage]:
repository = self.locked_repository(with_dev_reqs=dev) repository = self.locked_repository(with_dev_reqs=dev)
# Build a set of all packages required by our selected extras # Build a set of all packages required by our selected extras
...@@ -388,7 +395,7 @@ class Locker(object): ...@@ -388,7 +395,7 @@ class Locker(object):
yield DependencyPackage(dependency=dependency, package=package) 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() files = table()
packages = self._lock_packages(packages) packages = self._lock_packages(packages)
# Retrieving hashes # Retrieving hashes
...@@ -433,7 +440,7 @@ class Locker(object): ...@@ -433,7 +440,7 @@ class Locker(object):
return False return False
def _write_lock_data(self, data): # type: ("TOMLDocument") -> None def _write_lock_data(self, data: "TOMLDocument") -> None:
self.lock.write(data) self.lock.write(data)
# Checking lock file data consistency # Checking lock file data consistency
...@@ -442,7 +449,7 @@ class Locker(object): ...@@ -442,7 +449,7 @@ class Locker(object):
self._lock_data = None 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. Returns the sha256 hash of the sorted content of the pyproject file.
""" """
...@@ -458,7 +465,7 @@ class Locker(object): ...@@ -458,7 +465,7 @@ class Locker(object):
return content_hash return content_hash
def _get_lock_data(self): # type: () -> "TOMLDocument" def _get_lock_data(self) -> "TOMLDocument":
if not self._lock.exists(): if not self._lock.exists():
raise RuntimeError("No lockfile found. Unable to read locked packages") raise RuntimeError("No lockfile found. Unable to read locked packages")
...@@ -490,7 +497,7 @@ class Locker(object): ...@@ -490,7 +497,7 @@ class Locker(object):
return lock_data return lock_data
def _lock_packages(self, packages): # type: (List[Package]) -> list def _lock_packages(self, packages: List[Package]) -> list:
locked = [] locked = []
for package in sorted(packages, key=lambda x: x.name): for package in sorted(packages, key=lambda x: x.name):
...@@ -500,7 +507,7 @@ class Locker(object): ...@@ -500,7 +507,7 @@ class Locker(object):
return locked return locked
def _dump_package(self, package): # type: (Package) -> dict def _dump_package(self, package: Package) -> dict:
dependencies = {} dependencies = {}
for dependency in sorted(package.requires, key=lambda d: d.name): for dependency in sorted(package.requires, key=lambda d: d.name):
if dependency.pretty_name not in dependencies: if dependency.pretty_name not in dependencies:
......
...@@ -6,14 +6,16 @@ from .dependency_package import DependencyPackage ...@@ -6,14 +6,16 @@ from .dependency_package import DependencyPackage
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class PackageCollection(list): class PackageCollection(list):
def __init__( def __init__(
self, dependency, packages=None self,
): # type: (Dependency, List[Union["Package", DependencyPackage]]) -> None dependency: "Dependency",
packages: List[Union["Package", DependencyPackage]] = None,
) -> None:
self._dependency = dependency self._dependency = dependency
if packages is None: if packages is None:
...@@ -24,7 +26,7 @@ class PackageCollection(list): ...@@ -24,7 +26,7 @@ class PackageCollection(list):
for package in packages: for package in packages:
self.append(package) self.append(package)
def append(self, package): # type: (Union["Package", DependencyPackage]) -> None def append(self, package: Union["Package", DependencyPackage]) -> None:
if isinstance(package, DependencyPackage): if isinstance(package, DependencyPackage):
package = package.package package = package.package
......
...@@ -18,11 +18,11 @@ class Poetry(BasePoetry): ...@@ -18,11 +18,11 @@ class Poetry(BasePoetry):
def __init__( def __init__(
self, self,
file, # type: Path file: Path,
local_config, # type: dict local_config: dict,
package, # type: ProjectPackage package: ProjectPackage,
locker, # type: Locker locker: Locker,
config, # type: Config config: Config,
): ):
super(Poetry, self).__init__(file, local_config, package) super(Poetry, self).__init__(file, local_config, package)
...@@ -31,28 +31,28 @@ class Poetry(BasePoetry): ...@@ -31,28 +31,28 @@ class Poetry(BasePoetry):
self._pool = Pool() self._pool = Pool()
@property @property
def locker(self): # type: () -> Locker def locker(self) -> Locker:
return self._locker return self._locker
@property @property
def pool(self): # type: () -> Pool def pool(self) -> Pool:
return self._pool return self._pool
@property @property
def config(self): # type: () -> Config def config(self) -> Config:
return self._config return self._config
def set_locker(self, locker): # type: (Locker) -> Poetry def set_locker(self, locker: Locker) -> "Poetry":
self._locker = locker self._locker = locker
return self return self
def set_pool(self, pool): # type: (Pool) -> Poetry def set_pool(self, pool: Pool) -> "Poetry":
self._pool = pool self._pool = pool
return self return self
def set_config(self, config): # type: (Config) -> Poetry def set_config(self, config: Config) -> "Poetry":
self._config = config self._config = config
return self return self
...@@ -14,10 +14,10 @@ from .uploader import Uploader ...@@ -14,10 +14,10 @@ from .uploader import Uploader
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.io.buffered_io import BufferedIO # noqa from cleo.io import BufferedIO
from cleo.io.null_io import NullIO # noqa from cleo.io import ConsoleIO
from ..poetry import Poetry # noqa from ..poetry import Poetry
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -27,9 +27,7 @@ class Publisher: ...@@ -27,9 +27,7 @@ class Publisher:
Registers and publishes packages to remote repositories. Registers and publishes packages to remote repositories.
""" """
def __init__( def __init__(self, poetry: "Poetry", io: Union["BufferedIO", "ConsoleIO"]) -> None:
self, poetry, io
): # type: ("Poetry", Union["BufferedIO", "NullIO"]) -> None
self._poetry = poetry self._poetry = poetry
self._package = poetry.package self._package = poetry.package
self._io = io self._io = io
...@@ -37,18 +35,18 @@ class Publisher: ...@@ -37,18 +35,18 @@ class Publisher:
self._password_manager = PasswordManager(poetry.config) self._password_manager = PasswordManager(poetry.config)
@property @property
def files(self): # type: () -> List[Path] def files(self) -> List[Path]:
return self._uploader.files return self._uploader.files
def publish( def publish(
self, self,
repository_name, repository_name: Optional[str],
username, username: Optional[str],
password, password: Optional[str],
cert=None, cert: Optional[Path] = None,
client_cert=None, client_cert: Optional[Path] = None,
dry_run=False, dry_run: Optional[bool] = False,
): # type: (Optional[str], Optional[str], Optional[str], Optional[Path], Optional[Path], Optional[bool]) -> None ) -> None:
if not repository_name: if not repository_name:
url = "https://upload.pypi.org/legacy/" url = "https://upload.pypi.org/legacy/"
repository_name = "pypi" repository_name = "pypi"
......
...@@ -29,15 +29,15 @@ from poetry.utils.patterns import wheel_file_re ...@@ -29,15 +29,15 @@ from poetry.utils.patterns import wheel_file_re
if TYPE_CHECKING: 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") _has_blake2 = hasattr(hashlib, "blake2b")
class UploadError(Exception): 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): if isinstance(error, HTTPError):
message = "HTTP Error {}: {}".format( message = "HTTP Error {}: {}".format(
error.response.status_code, error.response.reason error.response.status_code, error.response.reason
...@@ -53,7 +53,7 @@ class UploadError(Exception): ...@@ -53,7 +53,7 @@ class UploadError(Exception):
class Uploader: class Uploader:
def __init__(self, poetry, io): # type: ("Poetry", "NullIO") -> None def __init__(self, poetry: "Poetry", io: "NullIO") -> None:
self._poetry = poetry self._poetry = poetry
self._package = poetry.package self._package = poetry.package
self._io = io self._io = io
...@@ -61,11 +61,11 @@ class Uploader: ...@@ -61,11 +61,11 @@ class Uploader:
self._password = None self._password = None
@property @property
def user_agent(self): # type: () -> str def user_agent(self) -> str:
return user_agent("poetry", __version__) return user_agent("poetry", __version__)
@property @property
def adapter(self): # type: () -> adapters.HTTPAdapter def adapter(self) -> adapters.HTTPAdapter:
retry = util.Retry( retry = util.Retry(
connect=5, connect=5,
total=10, total=10,
...@@ -76,7 +76,7 @@ class Uploader: ...@@ -76,7 +76,7 @@ class Uploader:
return adapters.HTTPAdapter(max_retries=retry) return adapters.HTTPAdapter(max_retries=retry)
@property @property
def files(self): # type: () -> List[Path] def files(self) -> List[Path]:
dist = self._poetry.file.parent / "dist" dist = self._poetry.file.parent / "dist"
version = normalize_version(self._package.version.text) version = normalize_version(self._package.version.text)
...@@ -93,11 +93,11 @@ class Uploader: ...@@ -93,11 +93,11 @@ class Uploader:
return sorted(wheels + tars) 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._username = username
self._password = password self._password = password
def make_session(self): # type: () -> requests.Session def make_session(self) -> requests.Session:
session = requests.session() session = requests.session()
if self.is_authenticated(): if self.is_authenticated():
session.auth = (self._username, self._password) session.auth = (self._username, self._password)
...@@ -108,12 +108,16 @@ class Uploader: ...@@ -108,12 +108,16 @@ class Uploader:
return session 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 return self._username is not None and self._password is not None
def upload( def upload(
self, url, cert=None, client_cert=None, dry_run=False self,
): # type: (str, Optional[Path], Optional[Path], bool) -> None url: str,
cert: Optional[Path] = None,
client_cert: Optional[Path] = None,
dry_run: bool = False,
) -> None:
session = self.make_session() session = self.make_session()
if cert: if cert:
...@@ -127,7 +131,7 @@ class Uploader: ...@@ -127,7 +131,7 @@ class Uploader:
finally: finally:
session.close() 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) meta = Metadata.from_package(self._package)
file_type = self._get_type(file) file_type = self._get_type(file)
...@@ -206,8 +210,8 @@ class Uploader: ...@@ -206,8 +210,8 @@ class Uploader:
return data return data
def _upload( def _upload(
self, session, url, dry_run=False self, session: requests.Session, url: str, dry_run: Optional[bool] = False
): # type: (requests.Session, str, Optional[bool]) -> None ) -> None:
try: try:
self._do_upload(session, url, dry_run) self._do_upload(session, url, dry_run)
except HTTPError as e: except HTTPError as e:
...@@ -223,8 +227,8 @@ class Uploader: ...@@ -223,8 +227,8 @@ class Uploader:
raise UploadError(e) raise UploadError(e)
def _do_upload( def _do_upload(
self, session, url, dry_run=False self, session: requests.Session, url: str, dry_run: Optional[bool] = False
): # type: (requests.Session, str, Optional[bool]) -> None ) -> None:
for file in self.files: for file in self.files:
# TODO: Check existence # TODO: Check existence
...@@ -234,8 +238,12 @@ class Uploader: ...@@ -234,8 +238,12 @@ class Uploader:
resp.raise_for_status() resp.raise_for_status()
def _upload_file( def _upload_file(
self, session, url, file, dry_run=False self,
): # type: (requests.Session, str, Path, Optional[bool]) -> requests.Response session: requests.Session,
url: str,
file: Path,
dry_run: Optional[bool] = False,
) -> requests.Response:
from cleo.ui.progress_bar import ProgressBar from cleo.ui.progress_bar import ProgressBar
data = self.post_data(file) data = self.post_data(file)
...@@ -305,9 +313,7 @@ class Uploader: ...@@ -305,9 +313,7 @@ class Uploader:
return resp return resp
def _register( def _register(self, session: requests.Session, url: str) -> requests.Response:
self, session, url
): # type: (requests.Session, str) -> requests.Response
""" """
Register a package to a repository. Register a package to a repository.
""" """
...@@ -335,7 +341,7 @@ class Uploader: ...@@ -335,7 +341,7 @@ class Uploader:
return resp 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 = [] data_to_send = []
for key, value in data.items(): for key, value in data.items():
if not isinstance(value, (list, tuple)): if not isinstance(value, (list, tuple)):
...@@ -346,7 +352,7 @@ class Uploader: ...@@ -346,7 +352,7 @@ class Uploader:
return data_to_send return data_to_send
def _get_type(self, file): # type: (Path) -> str def _get_type(self, file: Path) -> str:
exts = file.suffixes exts = file.suffixes
if exts[-1] == ".whl": if exts[-1] == ".whl":
return "bdist_wheel" return "bdist_wheel"
......
...@@ -3,20 +3,20 @@ from typing import Tuple ...@@ -3,20 +3,20 @@ from typing import Tuple
class SolverProblemError(Exception): class SolverProblemError(Exception):
def __init__(self, error): # type: (Exception) -> None def __init__(self, error: Exception) -> None:
self._error = error self._error = error
super(SolverProblemError, self).__init__(str(error)) super(SolverProblemError, self).__init__(str(error))
@property @property
def error(self): # type: () -> Exception def error(self) -> Exception:
return self._error return self._error
class OverrideNeeded(Exception): class OverrideNeeded(Exception):
def __init__(self, *overrides): # type: (*Dict) -> None def __init__(self, *overrides: Dict) -> None:
self._overrides = overrides self._overrides = overrides
@property @property
def overrides(self): # type: () -> Tuple[Dict] def overrides(self) -> Tuple[Dict]:
return self._overrides return self._overrides
...@@ -46,7 +46,7 @@ logger = logging.getLogger(__name__) ...@@ -46,7 +46,7 @@ logger = logging.getLogger(__name__)
class Indicator(ProgressIndicator): class Indicator(ProgressIndicator):
def _formatter_elapsed(self): def _formatter_elapsed(self) -> str:
elapsed = time.time() - self._start_time elapsed = time.time() - self._start_time
return "{:.1f}s".format(elapsed) return "{:.1f}s".format(elapsed)
...@@ -57,8 +57,8 @@ class Provider: ...@@ -57,8 +57,8 @@ class Provider:
UNSAFE_PACKAGES = {"setuptools", "distribute", "pip", "wheel"} UNSAFE_PACKAGES = {"setuptools", "distribute", "pip", "wheel"}
def __init__( def __init__(
self, package, pool, io, env=None self, package: Package, pool: Pool, io: Any, env: Optional[Env] = None
): # type: (Package, Pool, Any, Optional[Env]) -> None ) -> None:
self._package = package self._package = package
self._pool = pool self._pool = pool
self._io = io self._io = io
...@@ -72,20 +72,20 @@ class Provider: ...@@ -72,20 +72,20 @@ class Provider:
self._load_deferred = True self._load_deferred = True
@property @property
def pool(self): # type: () -> Pool def pool(self) -> Pool:
return self._pool return self._pool
def is_debugging(self): # type: () -> bool def is_debugging(self) -> bool:
return self._is_debugging return self._is_debugging
def set_overrides(self, overrides): # type: (Dict) -> None def set_overrides(self, overrides: Dict) -> None:
self._overrides = overrides 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 self._load_deferred = load_deferred
@contextmanager @contextmanager
def use_environment(self, env): # type: (Env) -> Provider def use_environment(self, env: Env) -> "Provider":
original_env = self._env original_env = self._env
original_python_constraint = self._python_constraint original_python_constraint = self._python_constraint
...@@ -98,8 +98,15 @@ class Provider: ...@@ -98,8 +98,15 @@ class Provider:
self._python_constraint = original_python_constraint self._python_constraint = original_python_constraint
def search_for( def search_for(
self, dependency self,
): # type: (Union[Dependency, VCSDependency, FileDependency, DirectoryDependency, URLDependency]) -> List[DependencyPackage] dependency: Union[
Dependency,
VCSDependency,
FileDependency,
DirectoryDependency,
URLDependency,
],
) -> List[DependencyPackage]:
""" """
Search for the specifications that match the given dependency. Search for the specifications that match the given dependency.
...@@ -154,7 +161,7 @@ class Provider: ...@@ -154,7 +161,7 @@ class Provider:
return PackageCollection(dependency, packages) 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. Search for the specifications that match the given VCS dependency.
...@@ -183,8 +190,14 @@ class Provider: ...@@ -183,8 +190,14 @@ class Provider:
@classmethod @classmethod
def get_package_from_vcs( def get_package_from_vcs(
cls, vcs, url, branch=None, tag=None, rev=None, name=None cls,
): # type: (str, str, Optional[str], Optional[str], Optional[str], Optional[str]) -> Package vcs: str,
url: str,
branch: Optional[str] = None,
tag: Optional[str] = None,
rev: Optional[str] = None,
name: Optional[str] = None,
) -> Package:
if vcs != "git": if vcs != "git":
raise ValueError("Unsupported VCS dependency {}".format(vcs)) raise ValueError("Unsupported VCS dependency {}".format(vcs))
...@@ -215,7 +228,7 @@ class Provider: ...@@ -215,7 +228,7 @@ class Provider:
return package 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: if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency] dependency, _package = self._deferred_cache[dependency]
...@@ -246,7 +259,7 @@ class Provider: ...@@ -246,7 +259,7 @@ class Provider:
return [package] return [package]
@classmethod @classmethod
def get_package_from_file(cls, file_path): # type: (Path) -> Package def get_package_from_file(cls, file_path: Path) -> Package:
try: try:
package = PackageInfo.from_path(path=file_path).to_package( package = PackageInfo.from_path(path=file_path).to_package(
root_dir=file_path root_dir=file_path
...@@ -258,9 +271,7 @@ class Provider: ...@@ -258,9 +271,7 @@ class Provider:
return package return package
def search_for_directory( def search_for_directory(self, dependency: DirectoryDependency) -> List[Package]:
self, dependency
): # type: (DirectoryDependency) -> List[Package]
if dependency in self._deferred_cache: if dependency in self._deferred_cache:
dependency, _package = self._deferred_cache[dependency] dependency, _package = self._deferred_cache[dependency]
...@@ -284,8 +295,8 @@ class Provider: ...@@ -284,8 +295,8 @@ class Provider:
@classmethod @classmethod
def get_package_from_directory( def get_package_from_directory(
cls, directory, name=None cls, directory: Path, name: Optional[str] = None
): # type: (Path, Optional[str]) -> Package ) -> Package:
package = PackageInfo.from_directory(path=directory).to_package( package = PackageInfo.from_directory(path=directory).to_package(
root_dir=directory root_dir=directory
) )
...@@ -300,7 +311,7 @@ class Provider: ...@@ -300,7 +311,7 @@ class Provider:
return package 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: if dependency in self._deferred_cache:
return [self._deferred_cache[dependency]] return [self._deferred_cache[dependency]]
...@@ -329,7 +340,7 @@ class Provider: ...@@ -329,7 +340,7 @@ class Provider:
return [package] return [package]
@classmethod @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: with temporary_directory() as temp_dir:
temp_dir = Path(temp_dir) temp_dir = Path(temp_dir)
file_name = os.path.basename(urllib.parse.urlparse(url).path) file_name = os.path.basename(urllib.parse.urlparse(url).path)
...@@ -343,8 +354,8 @@ class Provider: ...@@ -343,8 +354,8 @@ class Provider:
return package return package
def incompatibilities_for( def incompatibilities_for(
self, package self, package: DependencyPackage
): # type: (DependencyPackage) -> List[Incompatibility] ) -> List[Incompatibility]:
""" """
Returns incompatibilities that encapsulate a given package's dependencies, Returns incompatibilities that encapsulate a given package's dependencies,
or that it can't be safely selected. or that it can't be safely selected.
...@@ -419,9 +430,7 @@ class Provider: ...@@ -419,9 +430,7 @@ class Provider:
for dep in dependencies for dep in dependencies
] ]
def complete_package( def complete_package(self, package: DependencyPackage) -> DependencyPackage:
self, package
): # type: (DependencyPackage) -> DependencyPackage
if package.is_root(): if package.is_root():
package = package.clone() package = package.clone()
...@@ -695,7 +704,7 @@ class Provider: ...@@ -695,7 +704,7 @@ class Provider:
return package 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()): if not (self._io.is_very_verbose() or self._io.is_debug()):
return return
...@@ -782,7 +791,7 @@ class Provider: ...@@ -782,7 +791,7 @@ class Provider:
self._io.write(debug_info) self._io.write(debug_info)
@contextmanager @contextmanager
def progress(self): # type: () -> Iterator[None] def progress(self) -> Iterator[None]:
if not self._io.output.is_decorated() or self.is_debugging(): if not self._io.output.is_decorated() or self.is_debugging():
self._io.write_line("Resolving dependencies...") self._io.write_line("Resolving dependencies...")
yield yield
......
...@@ -31,24 +31,24 @@ from .provider import Provider ...@@ -31,24 +31,24 @@ from .provider import Provider
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import DirectoryDependency # noqa from poetry.core.packages import DirectoryDependency
from poetry.core.packages import FileDependency # noqa from poetry.core.packages import FileDependency
from poetry.core.packages import URLDependency # noqa from poetry.core.packages import URLDependency
from poetry.core.packages import VCSDependency # noqa from poetry.core.packages import VCSDependency
from poetry.installation.operations import OperationTypes # noqa from poetry.installation.operations import OperationTypes
class Solver: class Solver:
def __init__( def __init__(
self, self,
package, # type: ProjectPackage package: ProjectPackage,
pool, # type: Pool pool: Pool,
installed, # type: Repository installed: Repository,
locked, # type: Repository locked: Repository,
io, # type: IO io: IO,
remove_untracked=False, # type: bool remove_untracked: bool = False,
provider=None, # type: Optional[Provider] provider: Optional[Provider] = None,
): ):
self._package = package self._package = package
self._pool = pool self._pool = pool
...@@ -64,15 +64,15 @@ class Solver: ...@@ -64,15 +64,15 @@ class Solver:
self._remove_untracked = remove_untracked self._remove_untracked = remove_untracked
@property @property
def provider(self): # type: () -> Provider def provider(self) -> Provider:
return self._provider return self._provider
@contextmanager @contextmanager
def use_environment(self, env): # type: (Env) -> None def use_environment(self, env: Env) -> None:
with self.provider.use_environment(env): with self.provider.use_environment(env):
yield 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(): with self._provider.progress():
start = time.time() start = time.time()
packages, depths = self._solve(use_latest=use_latest) packages, depths = self._solve(use_latest=use_latest)
...@@ -210,8 +210,8 @@ class Solver: ...@@ -210,8 +210,8 @@ class Solver:
) )
def solve_in_compatibility_mode( def solve_in_compatibility_mode(
self, overrides, use_latest=None self, overrides: Tuple[Dict], use_latest: List[str] = None
): # type: (Tuple[Dict], List[str]) -> Tuple[List["Package"], List[int]] ) -> Tuple[List["Package"], List[int]]:
locked = {} locked = {}
for package in self._locked.packages: for package in self._locked.packages:
locked[package.name] = DependencyPackage(package.to_dependency(), package) locked[package.name] = DependencyPackage(package.to_dependency(), package)
...@@ -241,9 +241,7 @@ class Solver: ...@@ -241,9 +241,7 @@ class Solver:
return packages, depths return packages, depths
def _solve( def _solve(self, use_latest: List[str] = None) -> Tuple[List[Package], List[int]]:
self, use_latest=None
): # type: (List[str]) -> Tuple[List[Package], List[int]]
if self._provider._overrides: if self._provider._overrides:
self._overrides.append(self._provider._overrides) self._overrides.append(self._provider._overrides)
...@@ -296,20 +294,18 @@ class Solver: ...@@ -296,20 +294,18 @@ class Solver:
class DFSNode(object): class DFSNode(object):
def __init__( def __init__(self, id: Tuple[str, str, bool], name: str, base_name: str) -> None:
self, id, name, base_name
): # type: (Tuple[str, str, bool], str, str) -> None
self.id = id self.id = id
self.name = name self.name = name
self.base_name = base_name self.base_name = base_name
def reachable(self): # type: () -> List def reachable(self) -> List:
return [] return []
def visit(self, parents): # type: (List[PackageNode]) -> None def visit(self, parents: List["PackageNode"]) -> None:
pass pass
def __str__(self): # type: () -> str def __str__(self) -> str:
return str(self.id) return str(self.id)
...@@ -320,8 +316,8 @@ class VisitedState(enum.Enum): ...@@ -320,8 +316,8 @@ class VisitedState(enum.Enum):
def depth_first_search( def depth_first_search(
source, aggregator source: "PackageNode", aggregator: Callable
): # type: (PackageNode, Callable) -> List[Tuple[Package, int]] ) -> List[Tuple[Package, int]]:
back_edges = defaultdict(list) back_edges = defaultdict(list)
visited = {} visited = {}
topo_sorted_nodes = [] topo_sorted_nodes = []
...@@ -349,8 +345,11 @@ def depth_first_search( ...@@ -349,8 +345,11 @@ def depth_first_search(
def dfs_visit( def dfs_visit(
node, back_edges, visited, sorted_nodes node: "PackageNode",
): # type: (PackageNode, Dict[str, List[PackageNode]], Dict[str, VisitedState], List[PackageNode]) -> bool back_edges: Dict[str, List["PackageNode"]],
visited: Dict[str, VisitedState],
sorted_nodes: List["PackageNode"],
) -> bool:
if visited.get(node.id, VisitedState.Unvisited) == VisitedState.Visited: if visited.get(node.id, VisitedState.Unvisited) == VisitedState.Visited:
return True return True
if visited.get(node.id, VisitedState.Unvisited) == VisitedState.PartiallyVisited: if visited.get(node.id, VisitedState.Unvisited) == VisitedState.PartiallyVisited:
...@@ -372,12 +371,28 @@ def dfs_visit( ...@@ -372,12 +371,28 @@ def dfs_visit(
class PackageNode(DFSNode): class PackageNode(DFSNode):
def __init__( def __init__(
self, self,
package, # type: Package package: Package,
packages, # type: List[Package] packages: List[Package],
previous=None, # type: Optional[PackageNode] previous: Optional["PackageNode"] = None,
previous_dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]] previous_dep: Optional[
dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]] Union[
): # type: (...) -> None "DirectoryDependency",
"FileDependency",
"URLDependency",
"VCSDependency",
"Dependency",
]
] = None,
dep: Optional[
Union[
"DirectoryDependency",
"FileDependency",
"URLDependency",
"VCSDependency",
"Dependency",
]
] = None,
) -> None:
self.package = package self.package = package
self.packages = packages self.packages = packages
...@@ -399,8 +414,8 @@ class PackageNode(DFSNode): ...@@ -399,8 +414,8 @@ class PackageNode(DFSNode):
package.name, package.name,
) )
def reachable(self): # type: () -> List[PackageNode] def reachable(self) -> List["PackageNode"]:
children = [] # type: List[PackageNode] children: List[PackageNode] = []
if ( if (
self.previous_dep self.previous_dep
...@@ -446,7 +461,7 @@ class PackageNode(DFSNode): ...@@ -446,7 +461,7 @@ class PackageNode(DFSNode):
return children 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 # 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. # So that the root package's top-level dependencies have depth 0.
self.depth = 1 + max( self.depth = 1 + max(
...@@ -459,8 +474,8 @@ class PackageNode(DFSNode): ...@@ -459,8 +474,8 @@ class PackageNode(DFSNode):
def aggregate_package_nodes( def aggregate_package_nodes(
nodes, children nodes: List[PackageNode], children: List[PackageNode]
): # type: (List[PackageNode], List[PackageNode]) -> Tuple[Package, int] ) -> Tuple[Package, int]:
package = nodes[0].package package = nodes[0].package
depth = max(node.depth for node in nodes) depth = max(node.depth for node in nodes)
category = ( category = (
......
...@@ -4,28 +4,28 @@ from typing import Optional ...@@ -4,28 +4,28 @@ from typing import Optional
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class BaseRepository(object): class BaseRepository(object):
def __init__(self): # type: () -> None def __init__(self) -> None:
self._packages = [] self._packages = []
@property @property
def packages(self): # type: () -> List["Package"] def packages(self) -> List["Package"]:
return self._packages return self._packages
def has_package(self, package): # type: ("Package") -> None def has_package(self, package: "Package") -> None:
raise NotImplementedError() raise NotImplementedError()
def package( def package(
self, name, version, extras=None self, name: str, version: str, extras: Optional[List[str]] = None
): # type: (str, str, Optional[List[str]]) -> None ) -> None:
raise NotImplementedError() raise NotImplementedError()
def find_packages(self, dependency): # type: ("Dependency") -> None def find_packages(self, dependency: "Dependency") -> None:
raise NotImplementedError() raise NotImplementedError()
def search(self, query): # type: (str) -> None def search(self, query: str) -> None:
raise NotImplementedError() raise NotImplementedError()
...@@ -23,7 +23,7 @@ except NameError: ...@@ -23,7 +23,7 @@ except NameError:
class InstalledRepository(Repository): class InstalledRepository(Repository):
@classmethod @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 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 paths. We skip executable .pth files as there is no reliable means to do this
...@@ -68,9 +68,7 @@ class InstalledRepository(Repository): ...@@ -68,9 +68,7 @@ class InstalledRepository(Repository):
return paths return paths
@classmethod @classmethod
def set_package_vcs_properties_from_path( def set_package_vcs_properties_from_path(cls, src: Path, package: Package) -> None:
cls, src, package
): # type: (Path, Package) -> None
from poetry.core.vcs.git import Git from poetry.core.vcs.git import Git
git = Git() git = Git()
...@@ -82,12 +80,12 @@ class InstalledRepository(Repository): ...@@ -82,12 +80,12 @@ class InstalledRepository(Repository):
package._source_reference = revision package._source_reference = revision
@classmethod @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 src = env.path / "src" / package.name
cls.set_package_vcs_properties_from_path(src, package) cls.set_package_vcs_properties_from_path(src, package)
@classmethod @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 # A VCS dependency should have been installed
# in the src directory. # in the src directory.
src = env.path / "src" src = env.path / "src"
...@@ -102,7 +100,7 @@ class InstalledRepository(Repository): ...@@ -102,7 +100,7 @@ class InstalledRepository(Repository):
return True return True
@classmethod @classmethod
def load(cls, env): # type: (Env) -> InstalledRepository def load(cls, env: Env) -> "InstalledRepository":
""" """
Load installed packages. Load installed packages.
""" """
......
...@@ -8,7 +8,7 @@ from pathlib import Path ...@@ -8,7 +8,7 @@ from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import Generator from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
...@@ -38,7 +38,7 @@ from .pypi_repository import PyPiRepository ...@@ -38,7 +38,7 @@ from .pypi_repository import PyPiRepository
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
try: try:
from html import unescape from html import unescape
...@@ -75,9 +75,7 @@ class Page: ...@@ -75,9 +75,7 @@ class Page:
".tar", ".tar",
] ]
def __init__( def __init__(self, url: str, content: str, headers: Dict[str, Any]) -> None:
self, url, content, headers
): # type: (str, str, Dict[str, Any]) -> None
if not url.endswith("/"): if not url.endswith("/"):
url += "/" url += "/"
...@@ -99,7 +97,7 @@ class Page: ...@@ -99,7 +97,7 @@ class Page:
) )
@property @property
def versions(self): # type: () -> Generator[Version] def versions(self) -> Iterator[Version]:
seen = set() seen = set()
for link in self.links: for link in self.links:
version = self.link_version(link) version = self.link_version(link)
...@@ -115,7 +113,7 @@ class Page: ...@@ -115,7 +113,7 @@ class Page:
yield version yield version
@property @property
def links(self): # type: () -> Generator[Link] def links(self) -> Iterator[Link]:
for anchor in self._parsed.findall(".//a"): for anchor in self._parsed.findall(".//a"):
if anchor.get("href"): if anchor.get("href"):
href = anchor.get("href") href = anchor.get("href")
...@@ -130,12 +128,12 @@ class Page: ...@@ -130,12 +128,12 @@ class Page:
yield link 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: for link in self.links:
if self.link_version(link) == version: if self.link_version(link) == version:
yield link 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) m = wheel_file_re.match(link.filename)
if m: if m:
version = m.group("ver") version = m.group("ver")
...@@ -156,7 +154,7 @@ class Page: ...@@ -156,7 +154,7 @@ class Page:
_clean_re = re.compile(r"[^a-z0-9$&+,/:;=?@.#%_\\|-]", re.I) _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 """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 the link, it will be rewritten to %20 (while not over-quoting
% or other characters).""" % or other characters)."""
...@@ -165,8 +163,14 @@ class Page: ...@@ -165,8 +163,14 @@ class Page:
class LegacyRepository(PyPiRepository): class LegacyRepository(PyPiRepository):
def __init__( def __init__(
self, name, url, config=None, disable_cache=False, cert=None, client_cert=None self,
): # type: (str, str, Optional[Config], bool, Optional[Path], Optional[Path]) -> None 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": if name == "pypi":
raise ValueError("The name [pypi] is reserved for repositories") raise ValueError("The name [pypi] is reserved for repositories")
...@@ -211,15 +215,15 @@ class LegacyRepository(PyPiRepository): ...@@ -211,15 +215,15 @@ class LegacyRepository(PyPiRepository):
self._disable_cache = disable_cache self._disable_cache = disable_cache
@property @property
def cert(self): # type: () -> Optional[Path] def cert(self) -> Optional[Path]:
return self._cert return self._cert
@property @property
def client_cert(self): # type: () -> Optional[Path] def client_cert(self) -> Optional[Path]:
return self._client_cert return self._client_cert
@property @property
def authenticated_url(self): # type: () -> str def authenticated_url(self) -> str:
if not self._session.auth: if not self._session.auth:
return self.url return self.url
...@@ -233,7 +237,7 @@ class LegacyRepository(PyPiRepository): ...@@ -233,7 +237,7 @@ class LegacyRepository(PyPiRepository):
path=parsed.path, path=parsed.path,
) )
def find_packages(self, dependency): # type: ("Dependency") -> List[Package] def find_packages(self, dependency: "Dependency") -> List[Package]:
packages = [] packages = []
constraint = dependency.constraint constraint = dependency.constraint
...@@ -305,8 +309,8 @@ class LegacyRepository(PyPiRepository): ...@@ -305,8 +309,8 @@ class LegacyRepository(PyPiRepository):
return packages return packages
def package( def package(
self, name, version, extras=None self, name: str, version: str, extras: Optional[List[str]] = None
): # type: (str, str, Optional[List[str]]) -> Package ) -> Package:
""" """
Retrieve the release information. Retrieve the release information.
...@@ -330,14 +334,14 @@ class LegacyRepository(PyPiRepository): ...@@ -330,14 +334,14 @@ class LegacyRepository(PyPiRepository):
return package 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(".", "-"))) page = self._get("/{}/".format(package.name.replace(".", "-")))
if page is None: if page is None:
return [] return []
return list(page.links_for_version(package.version)) return list(page.links_for_version(package.version))
def _get_release_info(self, name, version): # type: (str, str) -> dict def _get_release_info(self, name: str, version: str) -> dict:
page = self._get("/{}/".format(canonicalize_name(name).replace(".", "-"))) page = self._get("/{}/".format(canonicalize_name(name).replace(".", "-")))
if page is None: if page is None:
raise PackageNotFound('No package named "{}"'.format(name)) raise PackageNotFound('No package named "{}"'.format(name))
...@@ -385,7 +389,7 @@ class LegacyRepository(PyPiRepository): ...@@ -385,7 +389,7 @@ class LegacyRepository(PyPiRepository):
return data.asdict() return data.asdict()
def _get(self, endpoint): # type: (str) -> Optional[Page] def _get(self, endpoint: str) -> Optional[Page]:
url = self._url + endpoint url = self._url + endpoint
try: try:
response = self.session.get(url) response = self.session.get(url)
......
...@@ -9,19 +9,21 @@ from .repository import Repository ...@@ -9,19 +9,21 @@ from .repository import Repository
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Pool(BaseRepository): class Pool(BaseRepository):
def __init__( def __init__(
self, repositories=None, ignore_repository_names=False self,
): # type: (Optional[List[Repository]], bool) -> None repositories: Optional[List[Repository]] = None,
ignore_repository_names: bool = False,
) -> None:
if repositories is None: if repositories is None:
repositories = [] repositories = []
self._lookup = {} # type: Dict[str, int] self._lookup: Dict[str, int] = {}
self._repositories = [] # type: List[Repository] self._repositories: List[Repository] = []
self._default = False self._default = False
self._secondary_start_idx = None self._secondary_start_idx = None
...@@ -33,18 +35,18 @@ class Pool(BaseRepository): ...@@ -33,18 +35,18 @@ class Pool(BaseRepository):
super(Pool, self).__init__() super(Pool, self).__init__()
@property @property
def repositories(self): # type: () -> List[Repository] def repositories(self) -> List[Repository]:
return self._repositories return self._repositories
def has_default(self): # type: () -> bool def has_default(self) -> bool:
return self._default 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 name = name.lower() if name is not None else None
return name in self._lookup return name in self._lookup
def repository(self, name): # type: (str) -> Repository def repository(self, name: str) -> Repository:
if name is not None: if name is not None:
name = name.lower() name = name.lower()
...@@ -54,8 +56,8 @@ class Pool(BaseRepository): ...@@ -54,8 +56,8 @@ class Pool(BaseRepository):
raise ValueError('Repository "{}" does not exist.'.format(name)) raise ValueError('Repository "{}" does not exist.'.format(name))
def add_repository( def add_repository(
self, repository, default=False, secondary=False self, repository: Repository, default: bool = False, secondary: bool = False
): # type: (Repository, bool, bool) -> Pool ) -> "Pool":
""" """
Adds a repository to the pool. Adds a repository to the pool.
""" """
...@@ -99,7 +101,7 @@ class Pool(BaseRepository): ...@@ -99,7 +101,7 @@ class Pool(BaseRepository):
return self 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: if repository_name is not None:
repository_name = repository_name.lower() repository_name = repository_name.lower()
...@@ -109,12 +111,12 @@ class Pool(BaseRepository): ...@@ -109,12 +111,12 @@ class Pool(BaseRepository):
return self return self
def has_package(self, package): # type: ("Package") -> bool def has_package(self, package: "Package") -> bool:
raise NotImplementedError() raise NotImplementedError()
def package( def package(
self, name, version, extras=None, repository=None self, name: str, version: str, extras: List[str] = None, repository: str = None
): # type: (str, str, List[str], str) -> "Package" ) -> "Package":
if repository is not None: if repository is not None:
repository = repository.lower() repository = repository.lower()
...@@ -144,7 +146,7 @@ class Pool(BaseRepository): ...@@ -144,7 +146,7 @@ class Pool(BaseRepository):
raise PackageNotFound("Package {} ({}) not found.".format(name, version)) 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 repository = dependency.source_name
if repository is not None: if repository is not None:
repository = repository.lower() repository = repository.lower()
...@@ -165,7 +167,7 @@ class Pool(BaseRepository): ...@@ -165,7 +167,7 @@ class Pool(BaseRepository):
return packages return packages
def search(self, query): # type: (str) -> List["Package"] def search(self, query: str) -> List["Package"]:
from .legacy_repository import LegacyRepository from .legacy_repository import LegacyRepository
results = [] results = []
......
...@@ -46,8 +46,11 @@ class PyPiRepository(RemoteRepository): ...@@ -46,8 +46,11 @@ class PyPiRepository(RemoteRepository):
CACHE_VERSION = parse_constraint("1.0.0") CACHE_VERSION = parse_constraint("1.0.0")
def __init__( def __init__(
self, url="https://pypi.org/", disable_cache=False, fallback=True self,
): # type: (str, bool, bool) -> None url: str = "https://pypi.org/",
disable_cache: bool = False,
fallback: bool = True,
) -> None:
super(PyPiRepository, self).__init__(url.rstrip("/") + "/simple/") super(PyPiRepository, self).__init__(url.rstrip("/") + "/simple/")
self._base_url = url self._base_url = url
...@@ -74,10 +77,10 @@ class PyPiRepository(RemoteRepository): ...@@ -74,10 +77,10 @@ class PyPiRepository(RemoteRepository):
self._name = "PyPI" self._name = "PyPI"
@property @property
def session(self): # type: () -> CacheControl def session(self) -> CacheControl:
return self._session return self._session
def find_packages(self, dependency): # type: (Dependency) -> List[Package] def find_packages(self, dependency: Dependency) -> List[Package]:
""" """
Find packages on the remote server. Find packages on the remote server.
""" """
...@@ -152,13 +155,13 @@ class PyPiRepository(RemoteRepository): ...@@ -152,13 +155,13 @@ class PyPiRepository(RemoteRepository):
def package( def package(
self, self,
name, # type: str name: str,
version, # type: str version: str,
extras=None, # type: (Union[list, None]) extras: (Union[list, None]) = None,
): # type: (...) -> Package ) -> Package:
return self.get_release_info(name, version).to_package(name=name, extras=extras) return self.get_release_info(name, version).to_package(name=name, extras=extras)
def search(self, query): # type: (str) -> List[Package] def search(self, query: str) -> List[Package]:
results = [] results = []
search = {"q": query} search = {"q": query}
...@@ -190,7 +193,7 @@ class PyPiRepository(RemoteRepository): ...@@ -190,7 +193,7 @@ class PyPiRepository(RemoteRepository):
return results return results
def get_package_info(self, name): # type: (str) -> dict def get_package_info(self, name: str) -> dict:
""" """
Return the package information given its name. Return the package information given its name.
...@@ -204,14 +207,14 @@ class PyPiRepository(RemoteRepository): ...@@ -204,14 +207,14 @@ class PyPiRepository(RemoteRepository):
name, lambda: self._get_package_info(name) name, lambda: self._get_package_info(name)
) )
def _get_package_info(self, name): # type: (str) -> dict def _get_package_info(self, name: str) -> dict:
data = self._get("pypi/{}/json".format(name)) data = self._get("pypi/{}/json".format(name))
if data is None: if data is None:
raise PackageNotFound("Package [{}] not found.".format(name)) raise PackageNotFound("Package [{}] not found.".format(name))
return data return data
def get_release_info(self, name, version): # type: (str, str) -> PackageInfo def get_release_info(self, name: str, version: str) -> PackageInfo:
""" """
Return the release information given a package name and a version. Return the release information given a package name and a version.
...@@ -238,7 +241,7 @@ class PyPiRepository(RemoteRepository): ...@@ -238,7 +241,7 @@ class PyPiRepository(RemoteRepository):
return PackageInfo.load(cached) return PackageInfo.load(cached)
def find_links_for_package(self, package): # type: (Package) -> List[Link] def find_links_for_package(self, package: Package) -> List[Link]:
json_data = self._get("pypi/{}/{}/json".format(package.name, package.version)) json_data = self._get("pypi/{}/{}/json".format(package.name, package.version))
if json_data is None: if json_data is None:
return [] return []
...@@ -250,7 +253,7 @@ class PyPiRepository(RemoteRepository): ...@@ -250,7 +253,7 @@ class PyPiRepository(RemoteRepository):
return links return links
def _get_release_info(self, name, version): # type: (str, str) -> dict def _get_release_info(self, name: str, version: str) -> dict:
self._log("Getting info for {} ({}) from PyPI".format(name, version), "debug") self._log("Getting info for {} ({}) from PyPI".format(name, version), "debug")
json_data = self._get("pypi/{}/{}/json".format(name, version)) json_data = self._get("pypi/{}/{}/json".format(name, version))
...@@ -311,7 +314,7 @@ class PyPiRepository(RemoteRepository): ...@@ -311,7 +314,7 @@ class PyPiRepository(RemoteRepository):
return data.asdict() return data.asdict()
def _get(self, endpoint): # type: (str) -> Union[dict, None] def _get(self, endpoint: str) -> Union[dict, None]:
try: try:
json_response = self.session.get(self._base_url + endpoint) json_response = self.session.get(self._base_url + endpoint)
except requests.exceptions.TooManyRedirects: except requests.exceptions.TooManyRedirects:
...@@ -327,7 +330,7 @@ class PyPiRepository(RemoteRepository): ...@@ -327,7 +330,7 @@ class PyPiRepository(RemoteRepository):
return json_data return json_data
def _get_info_from_urls(self, urls): # type: (Dict[str, List[str]]) -> PackageInfo def _get_info_from_urls(self, urls: Dict[str, List[str]]) -> PackageInfo:
# Checking wheels first as they are more likely to hold # Checking wheels first as they are more likely to hold
# the necessary information # the necessary information
if "bdist_wheel" in urls: if "bdist_wheel" in urls:
...@@ -419,7 +422,7 @@ class PyPiRepository(RemoteRepository): ...@@ -419,7 +422,7 @@ class PyPiRepository(RemoteRepository):
return self._get_info_from_sdist(urls["sdist"][0]) return self._get_info_from_sdist(urls["sdist"][0])
def _get_info_from_wheel(self, url): # type: (str) -> PackageInfo def _get_info_from_wheel(self, url: str) -> PackageInfo:
self._log( self._log(
"Downloading wheel: {}".format( "Downloading wheel: {}".format(
urllib.parse.urlparse(url).path.rsplit("/")[-1] urllib.parse.urlparse(url).path.rsplit("/")[-1]
...@@ -435,7 +438,7 @@ class PyPiRepository(RemoteRepository): ...@@ -435,7 +438,7 @@ class PyPiRepository(RemoteRepository):
return PackageInfo.from_wheel(filepath) return PackageInfo.from_wheel(filepath)
def _get_info_from_sdist(self, url): # type: (str) -> PackageInfo def _get_info_from_sdist(self, url: str) -> PackageInfo:
self._log( self._log(
"Downloading sdist: {}".format( "Downloading sdist: {}".format(
urllib.parse.urlparse(url).path.rsplit("/")[-1] urllib.parse.urlparse(url).path.rsplit("/")[-1]
...@@ -451,8 +454,8 @@ class PyPiRepository(RemoteRepository): ...@@ -451,8 +454,8 @@ class PyPiRepository(RemoteRepository):
return PackageInfo.from_sdist(filepath) return PackageInfo.from_sdist(filepath)
def _download(self, url, dest): # type: (str, str) -> None def _download(self, url: str, dest: str) -> None:
return download_file(url, dest, session=self.session) return download_file(url, dest, session=self.session)
def _log(self, msg, level="info"): # type: (str, str) -> None def _log(self, msg: str, level: str = "info") -> None:
getattr(logger, level)("<debug>{}:</debug> {}".format(self._name, msg)) getattr(logger, level)("<debug>{}:</debug> {}".format(self._name, msg))
...@@ -2,15 +2,15 @@ from .repository import Repository ...@@ -2,15 +2,15 @@ from .repository import Repository
class RemoteRepository(Repository): class RemoteRepository(Repository):
def __init__(self, url): # type: (str) -> None def __init__(self, url: str) -> None:
self._url = url self._url = url
super(RemoteRepository, self).__init__() super(RemoteRepository, self).__init__()
@property @property
def url(self): # type: () -> str def url(self) -> str:
return self._url return self._url
@property @property
def authenticated_url(self): # type: () -> str def authenticated_url(self) -> str:
return self._url return self._url
...@@ -10,15 +10,13 @@ from .base_repository import BaseRepository ...@@ -10,15 +10,13 @@ from .base_repository import BaseRepository
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa from poetry.core.packages import Dependency
from poetry.core.packages import Link # noqa from poetry.core.packages import Link
from poetry.core.packages import Package # noqa from poetry.core.packages import Package
class Repository(BaseRepository): class Repository(BaseRepository):
def __init__( def __init__(self, packages: List["Package"] = None, name: str = None) -> None:
self, packages=None, name=None
): # type: (List["Package"], str) -> None
super(Repository, self).__init__() super(Repository, self).__init__()
self._name = name self._name = name
...@@ -30,19 +28,19 @@ class Repository(BaseRepository): ...@@ -30,19 +28,19 @@ class Repository(BaseRepository):
self.add_package(package) self.add_package(package)
@property @property
def name(self): # type: () -> str def name(self) -> str:
return self._name return self._name
def package( def package(
self, name, version, extras=None self, name: str, version: str, extras: Optional[List[str]] = None
): # type: (str, str, Optional[List[str]]) -> "Package" ) -> "Package":
name = name.lower() name = name.lower()
for package in self.packages: for package in self.packages:
if name == package.name and package.version.text == version: if name == package.name and package.version.text == version:
return package.clone() return package.clone()
def find_packages(self, dependency): # type: ("Dependency") -> List["Package"] def find_packages(self, dependency: "Dependency") -> List["Package"]:
constraint = dependency.constraint constraint = dependency.constraint
packages = [] packages = []
ignored_pre_release_packages = [] ignored_pre_release_packages = []
...@@ -85,7 +83,7 @@ class Repository(BaseRepository): ...@@ -85,7 +83,7 @@ class Repository(BaseRepository):
return packages or ignored_pre_release_packages return packages or ignored_pre_release_packages
def has_package(self, package): # type: ("Package") -> bool def has_package(self, package: "Package") -> bool:
package_id = package.unique_name package_id = package.unique_name
for repo_package in self.packages: for repo_package in self.packages:
...@@ -94,10 +92,10 @@ class Repository(BaseRepository): ...@@ -94,10 +92,10 @@ class Repository(BaseRepository):
return False return False
def add_package(self, package): # type: ("Package") -> None def add_package(self, package: "Package") -> None:
self._packages.append(package) self._packages.append(package)
def remove_package(self, package): # type: ("Package") -> None def remove_package(self, package: "Package") -> None:
package_id = package.unique_name package_id = package.unique_name
index = None index = None
...@@ -109,10 +107,10 @@ class Repository(BaseRepository): ...@@ -109,10 +107,10 @@ class Repository(BaseRepository):
if index is not None: if index is not None:
del self._packages[index] del self._packages[index]
def find_links_for_package(self, package): # type: ("Package") -> List["Link"] def find_links_for_package(self, package: "Package") -> List["Link"]:
return [] return []
def search(self, query): # type: (str) -> List["Package"] def search(self, query: str) -> List["Package"]:
results = [] results = []
for package in self.packages: for package in self.packages:
...@@ -121,5 +119,5 @@ class Repository(BaseRepository): ...@@ -121,5 +119,5 @@ class Repository(BaseRepository):
return results return results
def __len__(self): # type: () -> int def __len__(self) -> int:
return len(self._packages) return len(self._packages)
...@@ -11,13 +11,13 @@ from typing import Union ...@@ -11,13 +11,13 @@ from typing import Union
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa from pathlib import Path
WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")
def expanduser(path): # type: (Union[str, "Path"]) -> str def expanduser(path: Union[str, "Path"]) -> str:
""" """
Expand ~ and ~user constructions. Expand ~ and ~user constructions.
...@@ -29,7 +29,7 @@ def expanduser(path): # type: (Union[str, "Path"]) -> str ...@@ -29,7 +29,7 @@ def expanduser(path): # type: (Union[str, "Path"]) -> str
return expanded return expanded
def user_cache_dir(appname): # type: (str) -> str def user_cache_dir(appname: str) -> str:
r""" r"""
Return full path to the user-specific cache dir for this application. Return full path to the user-specific cache dir for this application.
...@@ -72,7 +72,7 @@ def user_cache_dir(appname): # type: (str) -> str ...@@ -72,7 +72,7 @@ def user_cache_dir(appname): # type: (str) -> str
return path return path
def user_data_dir(appname, roaming=False): # type: (str, bool) -> str def user_data_dir(appname: str, roaming: bool = False) -> str:
r""" r"""
Return full path to the user-specific data dir for this application. Return full path to the user-specific data dir for this application.
...@@ -112,7 +112,7 @@ def user_data_dir(appname, roaming=False): # type: (str, bool) -> str ...@@ -112,7 +112,7 @@ def user_data_dir(appname, roaming=False): # type: (str, bool) -> str
return path return path
def user_config_dir(appname, roaming=True): # type: (str, bool) -> str def user_config_dir(appname: str, roaming: bool = True) -> str:
"""Return full path to the user-specific config dir for this application. """Return full path to the user-specific config dir for this application.
"appname" is the name of application. "appname" is the name of application.
...@@ -145,7 +145,7 @@ def user_config_dir(appname, roaming=True): # type: (str, bool) -> str ...@@ -145,7 +145,7 @@ def user_config_dir(appname, roaming=True): # type: (str, bool) -> str
# for the discussion regarding site_config_dirs locations # for the discussion regarding site_config_dirs locations
# see <https://github.com/pypa/pip/issues/1733> # see <https://github.com/pypa/pip/issues/1733>
def site_config_dirs(appname): # type: (str) -> List[str] def site_config_dirs(appname: str) -> List[str]:
r"""Return a list of potential user-shared config dirs for this application. r"""Return a list of potential user-shared config dirs for this application.
"appname" is the name of application. "appname" is the name of application.
...@@ -186,7 +186,7 @@ def site_config_dirs(appname): # type: (str) -> List[str] ...@@ -186,7 +186,7 @@ def site_config_dirs(appname): # type: (str) -> List[str]
# -- Windows support functions -- # -- Windows support functions --
def _get_win_folder_from_registry(csidl_name): # type: (str) -> str def _get_win_folder_from_registry(csidl_name: str) -> str:
""" """
This is a fallback technique at best. I'm not sure if using the This is a fallback technique at best. I'm not sure if using the
registry for this guarantees us the correct answer for all CSIDL_* registry for this guarantees us the correct answer for all CSIDL_*
...@@ -208,7 +208,7 @@ def _get_win_folder_from_registry(csidl_name): # type: (str) -> str ...@@ -208,7 +208,7 @@ def _get_win_folder_from_registry(csidl_name): # type: (str) -> str
return directory return directory
def _get_win_folder_with_ctypes(csidl_name): # type: (str) -> str def _get_win_folder_with_ctypes(csidl_name: str) -> str:
csidl_const = { csidl_const = {
"CSIDL_APPDATA": 26, "CSIDL_APPDATA": 26,
"CSIDL_COMMON_APPDATA": 35, "CSIDL_COMMON_APPDATA": 35,
...@@ -242,7 +242,7 @@ if WINDOWS: ...@@ -242,7 +242,7 @@ if WINDOWS:
_get_win_folder = _get_win_folder_from_registry _get_win_folder = _get_win_folder_from_registry
def _win_path_to_bytes(path): # type: (str) -> Union[str, bytes] def _win_path_to_bytes(path: str) -> Union[str, bytes]:
"""Encode Windows paths to bytes. Only used on Python 2. """Encode Windows paths to bytes. Only used on Python 2.
Motivation is to be consistent with other operating systems where paths Motivation is to be consistent with other operating systems where paths
......
...@@ -148,8 +148,8 @@ print(json.dumps(sysconfig.get_paths())) ...@@ -148,8 +148,8 @@ print(json.dumps(sysconfig.get_paths()))
class SitePackages: class SitePackages:
def __init__( def __init__(
self, path, fallbacks=None, skip_write_checks=False self, path: Path, fallbacks: List[Path] = None, skip_write_checks: bool = False
): # type: (Path, List[Path], bool) -> None ) -> None:
self._path = path self._path = path
self._fallbacks = fallbacks or [] self._fallbacks = fallbacks or []
self._skip_write_checks = skip_write_checks self._skip_write_checks = skip_write_checks
...@@ -157,15 +157,15 @@ class SitePackages: ...@@ -157,15 +157,15 @@ class SitePackages:
self._writable_candidates = None if not skip_write_checks else self._candidates self._writable_candidates = None if not skip_write_checks else self._candidates
@property @property
def path(self): # type: () -> Path def path(self) -> Path:
return self._path return self._path
@property @property
def candidates(self): # type: () -> List[Path] def candidates(self) -> List[Path]:
return self._candidates return self._candidates
@property @property
def writable_candidates(self): # type: () -> List[Path] def writable_candidates(self) -> List[Path]:
if self._writable_candidates is not None: if self._writable_candidates is not None:
return self._writable_candidates return self._writable_candidates
...@@ -177,9 +177,7 @@ class SitePackages: ...@@ -177,9 +177,7 @@ class SitePackages:
return self._writable_candidates return self._writable_candidates
def make_candidates( def make_candidates(self, path: Path, writable_only: bool = False) -> List[Path]:
self, path, writable_only=False
): # type: (Path, bool) -> List[Path]
candidates = self._candidates if not writable_only else self.writable_candidates candidates = self._candidates if not writable_only else self.writable_candidates
if path.is_absolute(): if path.is_absolute():
for candidate in candidates: for candidate in candidates:
...@@ -198,8 +196,8 @@ class SitePackages: ...@@ -198,8 +196,8 @@ class SitePackages:
return [candidate / path for candidate in candidates if candidate] return [candidate / path for candidate in candidates if candidate]
def _path_method_wrapper( def _path_method_wrapper(
self, path, method, *args, **kwargs self, path: Path, method: str, *args: Any, **kwargs: Any
): # type: (Path, str, *Any, **Any) -> Union[Tuple[Path, Any], List[Tuple[Path, Any]]] ) -> Union[Tuple[Path, Any], List[Tuple[Path, Any]]]:
# TODO: Move to parameters after dropping Python 2.7 # TODO: Move to parameters after dropping Python 2.7
return_first = kwargs.pop("return_first", True) return_first = kwargs.pop("return_first", True)
...@@ -232,19 +230,19 @@ class SitePackages: ...@@ -232,19 +230,19 @@ class SitePackages:
raise OSError("Unable to access any of {}".format(paths_csv(candidates))) raise OSError("Unable to access any of {}".format(paths_csv(candidates)))
def write_text(self, path, *args, **kwargs): # type: (Path, *Any, **Any) -> Path def write_text(self, path: Path, *args: Any, **kwargs: Any) -> Path:
return self._path_method_wrapper(path, "write_text", *args, **kwargs)[0] return self._path_method_wrapper(path, "write_text", *args, **kwargs)[0]
def mkdir(self, path, *args, **kwargs): # type: (Path, *Any, **Any) -> Path def mkdir(self, path: Path, *args: Any, **kwargs: Any) -> Path:
return self._path_method_wrapper(path, "mkdir", *args, **kwargs)[0] return self._path_method_wrapper(path, "mkdir", *args, **kwargs)[0]
def exists(self, path): # type: (Path) -> bool def exists(self, path: Path) -> bool:
return any( return any(
value[-1] value[-1]
for value in self._path_method_wrapper(path, "exists", return_first=False) for value in self._path_method_wrapper(path, "exists", return_first=False)
) )
def find(self, path, writable_only=False): # type: (Path, bool) -> List[Path] def find(self, path: Path, writable_only: bool = False) -> List[Path]:
return [ return [
value[0] value[0]
for value in self._path_method_wrapper( for value in self._path_method_wrapper(
...@@ -253,7 +251,7 @@ class SitePackages: ...@@ -253,7 +251,7 @@ class SitePackages:
if value[-1] is True if value[-1] is True
] ]
def __getattr__(self, item): # type: (str) -> Any def __getattr__(self, item: str) -> Any:
try: try:
return super(SitePackages, self).__getattribute__(item) return super(SitePackages, self).__getattribute__(item)
except AttributeError: except AttributeError:
...@@ -266,9 +264,7 @@ class EnvError(Exception): ...@@ -266,9 +264,7 @@ class EnvError(Exception):
class EnvCommandError(EnvError): class EnvCommandError(EnvError):
def __init__( def __init__(self, e: CalledProcessError, input: Optional[str] = None) -> None:
self, e, input=None
): # type: (CalledProcessError, Optional[str]) -> None
self.e = e self.e = e
message = "Command {} errored with the following return code {}, and output: \n{}".format( message = "Command {} errored with the following return code {}, and output: \n{}".format(
...@@ -280,7 +276,7 @@ class EnvCommandError(EnvError): ...@@ -280,7 +276,7 @@ class EnvCommandError(EnvError):
class NoCompatiblePythonVersionFound(EnvError): class NoCompatiblePythonVersionFound(EnvError):
def __init__(self, expected, given=None): # type: (str, Optional[str]) -> None def __init__(self, expected: str, given: Optional[str] = None) -> None:
if given: if given:
message = ( message = (
"The specified Python version ({}) " "The specified Python version ({}) "
...@@ -308,10 +304,10 @@ class EnvManager(object): ...@@ -308,10 +304,10 @@ class EnvManager(object):
ENVS_FILE = "envs.toml" ENVS_FILE = "envs.toml"
def __init__(self, poetry): # type: (Poetry) -> None def __init__(self, poetry: Poetry) -> None:
self._poetry = poetry self._poetry = poetry
def activate(self, python, io): # type: (str, IO) -> Env def activate(self, python: str, io: IO) -> "Env":
venv_path = self._poetry.config.get("virtualenvs.path") venv_path = self._poetry.config.get("virtualenvs.path")
if venv_path is None: if venv_path is None:
venv_path = Path(CACHE_DIR) / "virtualenvs" venv_path = Path(CACHE_DIR) / "virtualenvs"
...@@ -408,7 +404,7 @@ class EnvManager(object): ...@@ -408,7 +404,7 @@ class EnvManager(object):
return self.get(reload=True) return self.get(reload=True)
def deactivate(self, io): # type: (IO) -> None def deactivate(self, io: IO) -> None:
venv_path = self._poetry.config.get("virtualenvs.path") venv_path = self._poetry.config.get("virtualenvs.path")
if venv_path is None: if venv_path is None:
venv_path = Path(CACHE_DIR) / "virtualenvs" venv_path = Path(CACHE_DIR) / "virtualenvs"
...@@ -432,7 +428,7 @@ class EnvManager(object): ...@@ -432,7 +428,7 @@ class EnvManager(object):
envs_file.write(envs) envs_file.write(envs)
def get(self, reload=False): # type: (bool) -> Env def get(self, reload: bool = False) -> Union["VirtualEnv", "SystemEnv"]:
if self._env is not None and not reload: if self._env is not None and not reload:
return self._env return self._env
...@@ -500,7 +496,7 @@ class EnvManager(object): ...@@ -500,7 +496,7 @@ class EnvManager(object):
return VirtualEnv(prefix, base_prefix) return VirtualEnv(prefix, base_prefix)
def list(self, name=None): # type: (Optional[str]) -> List[VirtualEnv] def list(self, name: Optional[str] = None) -> List["VirtualEnv"]:
if name is None: if name is None:
name = self._poetry.package.name name = self._poetry.package.name
...@@ -526,7 +522,7 @@ class EnvManager(object): ...@@ -526,7 +522,7 @@ class EnvManager(object):
env_list.insert(0, VirtualEnv(venv)) env_list.insert(0, VirtualEnv(venv))
return env_list return env_list
def remove(self, python): # type: (str) -> Env def remove(self, python: str) -> "Env":
venv_path = self._poetry.config.get("virtualenvs.path") venv_path = self._poetry.config.get("virtualenvs.path")
if venv_path is None: if venv_path is None:
venv_path = Path(CACHE_DIR) / "virtualenvs" venv_path = Path(CACHE_DIR) / "virtualenvs"
...@@ -620,8 +616,12 @@ class EnvManager(object): ...@@ -620,8 +616,12 @@ class EnvManager(object):
return VirtualEnv(venv) return VirtualEnv(venv)
def create_venv( def create_venv(
self, io, name=None, executable=None, force=False self,
): # type: (IO, Optional[str], Optional[str], bool) -> VirtualEnv io: IO,
name: Optional[str] = None,
executable: Optional[str] = None,
force: bool = False,
) -> Union["SystemEnv", "VirtualEnv"]:
if self._env is not None and not force: if self._env is not None and not force:
return self._env return self._env
...@@ -806,8 +806,11 @@ class EnvManager(object): ...@@ -806,8 +806,11 @@ class EnvManager(object):
@classmethod @classmethod
def build_venv( def build_venv(
cls, path, executable=None, flags=None cls,
): # type: (Union[Path,str], Optional[Union[str, Path]], Dict[str, bool]) -> virtualenv.run.session.Session path: Union[Path, str],
executable: Optional[Union[str, Path]] = None,
flags: Dict[str, bool] = None,
) -> virtualenv.run.session.Session:
flags = flags or {} flags = flags or {}
if isinstance(executable, Path): if isinstance(executable, Path):
...@@ -828,7 +831,7 @@ class EnvManager(object): ...@@ -828,7 +831,7 @@ class EnvManager(object):
return virtualenv.cli_run(args) return virtualenv.cli_run(args)
@classmethod @classmethod
def remove_venv(cls, path): # type: (Union[Path,str]) -> None def remove_venv(cls, path: Union[Path, str]) -> None:
if isinstance(path, str): if isinstance(path, str):
path = Path(path) path = Path(path)
assert path.is_dir() assert path.is_dir()
...@@ -850,7 +853,7 @@ class EnvManager(object): ...@@ -850,7 +853,7 @@ class EnvManager(object):
elif file_path.is_dir(): elif file_path.is_dir():
shutil.rmtree(str(file_path)) shutil.rmtree(str(file_path))
def get_base_prefix(self): # type: () -> Path def get_base_prefix(self) -> Path:
if hasattr(sys, "real_prefix"): if hasattr(sys, "real_prefix"):
return Path(sys.real_prefix) return Path(sys.real_prefix)
...@@ -860,7 +863,7 @@ class EnvManager(object): ...@@ -860,7 +863,7 @@ class EnvManager(object):
return Path(sys.prefix) return Path(sys.prefix)
@classmethod @classmethod
def generate_env_name(cls, name, cwd): # type: (str, str) -> str def generate_env_name(cls, name: str, cwd: str) -> str:
name = name.lower() name = name.lower()
sanitized_name = re.sub(r'[ $`!*@"\\\r\n\t]', "_", name)[:42] sanitized_name = re.sub(r'[ $`!*@"\\\r\n\t]', "_", name)[:42]
h = hashlib.sha256(encode(cwd)).digest() h = hashlib.sha256(encode(cwd)).digest()
...@@ -874,7 +877,7 @@ class Env(object): ...@@ -874,7 +877,7 @@ class Env(object):
An abstract Python environment. An abstract Python environment.
""" """
def __init__(self, path, base=None): # type: (Path, Optional[Path]) -> None def __init__(self, path: Path, base: Optional[Path] = None) -> None:
self._is_windows = sys.platform == "win32" self._is_windows = sys.platform == "win32"
self._path = path self._path = path
...@@ -893,59 +896,59 @@ class Env(object): ...@@ -893,59 +896,59 @@ class Env(object):
self._script_dirs = None self._script_dirs = None
@property @property
def path(self): # type: () -> Path def path(self) -> Path:
return self._path return self._path
@property @property
def base(self): # type: () -> Path def base(self) -> Path:
return self._base return self._base
@property @property
def version_info(self): # type: () -> Tuple[int] def version_info(self) -> Tuple[int]:
return tuple(self.marker_env["version_info"]) return tuple(self.marker_env["version_info"])
@property @property
def python_implementation(self): # type: () -> str def python_implementation(self) -> str:
return self.marker_env["platform_python_implementation"] return self.marker_env["platform_python_implementation"]
@property @property
def python(self): # type: () -> str def python(self) -> str:
""" """
Path to current python executable Path to current python executable
""" """
return self._bin("python") return self._bin("python")
@property @property
def marker_env(self): # type: () -> Dict[str, Any] def marker_env(self) -> Dict[str, Any]:
if self._marker_env is None: if self._marker_env is None:
self._marker_env = self.get_marker_env() self._marker_env = self.get_marker_env()
return self._marker_env return self._marker_env
@property @property
def pip(self): # type: () -> str def pip(self) -> str:
""" """
Path to current pip executable Path to current pip executable
""" """
return self._bin("pip") return self._bin("pip")
@property @property
def platform(self): # type: () -> str def platform(self) -> str:
return sys.platform return sys.platform
@property @property
def os(self): # type: () -> str def os(self) -> str:
return os.name return os.name
@property @property
def pip_version(self): # type: () -> Version def pip_version(self) -> Version:
if self._pip_version is None: if self._pip_version is None:
self._pip_version = self.get_pip_version() self._pip_version = self.get_pip_version()
return self._pip_version return self._pip_version
@property @property
def site_packages(self): # type: () -> SitePackages def site_packages(self) -> SitePackages:
if self._site_packages is None: if self._site_packages is None:
# we disable write checks if no user site exist # we disable write checks if no user site exist
fallbacks = [self.usersite] if self.usersite else [] fallbacks = [self.usersite] if self.usersite else []
...@@ -955,24 +958,24 @@ class Env(object): ...@@ -955,24 +958,24 @@ class Env(object):
return self._site_packages return self._site_packages
@property @property
def usersite(self): # type: () -> Optional[Path] def usersite(self) -> Optional[Path]:
if "usersite" in self.paths: if "usersite" in self.paths:
return Path(self.paths["usersite"]) return Path(self.paths["usersite"])
@property @property
def userbase(self): # type: () -> Optional[Path] def userbase(self) -> Optional[Path]:
if "userbase" in self.paths: if "userbase" in self.paths:
return Path(self.paths["userbase"]) return Path(self.paths["userbase"])
@property @property
def purelib(self): # type: () -> Path def purelib(self) -> Path:
if self._purelib is None: if self._purelib is None:
self._purelib = Path(self.paths["purelib"]) self._purelib = Path(self.paths["purelib"])
return self._purelib return self._purelib
@property @property
def platlib(self): # type: () -> Path def platlib(self) -> Path:
if self._platlib is None: if self._platlib is None:
if "platlib" in self.paths: if "platlib" in self.paths:
self._platlib = Path(self.paths["platlib"]) self._platlib = Path(self.paths["platlib"])
...@@ -981,7 +984,7 @@ class Env(object): ...@@ -981,7 +984,7 @@ class Env(object):
return self._platlib return self._platlib
def is_path_relative_to_lib(self, path): # type: (Path) -> bool def is_path_relative_to_lib(self, path: Path) -> bool:
for lib_path in [self.purelib, self.platlib]: for lib_path in [self.purelib, self.platlib]:
try: try:
path.relative_to(lib_path) path.relative_to(lib_path)
...@@ -992,25 +995,25 @@ class Env(object): ...@@ -992,25 +995,25 @@ class Env(object):
return False return False
@property @property
def sys_path(self): # type: () -> List[str] def sys_path(self) -> List[str]:
raise NotImplementedError() raise NotImplementedError()
@property @property
def paths(self): # type: () -> Dict[str, str] def paths(self) -> Dict[str, str]:
if self._paths is None: if self._paths is None:
self._paths = self.get_paths() self._paths = self.get_paths()
return self._paths return self._paths
@property @property
def supported_tags(self): # type: () -> List[Tag] def supported_tags(self) -> List[Tag]:
if self._supported_tags is None: if self._supported_tags is None:
self._supported_tags = self.get_supported_tags() self._supported_tags = self.get_supported_tags()
return self._supported_tags return self._supported_tags
@classmethod @classmethod
def get_base_prefix(cls): # type: () -> Path def get_base_prefix(cls) -> Path:
if hasattr(sys, "real_prefix"): if hasattr(sys, "real_prefix"):
return Path(sys.real_prefix) return Path(sys.real_prefix)
...@@ -1019,47 +1022,47 @@ class Env(object): ...@@ -1019,47 +1022,47 @@ class Env(object):
return Path(sys.prefix) return Path(sys.prefix)
def get_version_info(self): # type: () -> Tuple[int] def get_version_info(self) -> Tuple[int]:
raise NotImplementedError() raise NotImplementedError()
def get_python_implementation(self): # type: () -> str def get_python_implementation(self) -> str:
raise NotImplementedError() raise NotImplementedError()
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self) -> Dict[str, Any]:
raise NotImplementedError() raise NotImplementedError()
def get_pip_command(self): # type: () -> List[str] def get_pip_command(self) -> List[str]:
raise NotImplementedError() raise NotImplementedError()
def get_supported_tags(self): # type: () -> List[Tag] def get_supported_tags(self) -> List[Tag]:
raise NotImplementedError() raise NotImplementedError()
def get_pip_version(self): # type: () -> Version def get_pip_version(self) -> Version:
raise NotImplementedError() raise NotImplementedError()
def get_paths(self): # type: () -> Dict[str, str] def get_paths(self) -> Dict[str, str]:
raise NotImplementedError() raise NotImplementedError()
def is_valid_for_marker(self, marker): # type: (BaseMarker) -> bool def is_valid_for_marker(self, marker: BaseMarker) -> bool:
return marker.validate(self.marker_env) return marker.validate(self.marker_env)
def is_sane(self): # type: () -> bool def is_sane(self) -> bool:
""" """
Checks whether the current environment is sane or not. Checks whether the current environment is sane or not.
""" """
return True return True
def run(self, bin, *args, **kwargs): # type: (str, *str, **Any) -> Union[str, int] def run(self, bin: str, *args: str, **kwargs: Any) -> Union[str, int]:
bin = self._bin(bin) bin = self._bin(bin)
cmd = [bin] + list(args) cmd = [bin] + list(args)
return self._run(cmd, **kwargs) return self._run(cmd, **kwargs)
def run_pip(self, *args, **kwargs): # type: (*str, **Any) -> Union[int, str] def run_pip(self, *args: str, **kwargs: Any) -> Union[int, str]:
pip = self.get_pip_command() pip = self.get_pip_command()
cmd = pip + list(args) cmd = pip + list(args)
return self._run(cmd, **kwargs) return self._run(cmd, **kwargs)
def _run(self, cmd, **kwargs): # type: (List[str], **Any) -> Union[int, str] def _run(self, cmd: List[str], **kwargs: Any) -> Union[int, str]:
""" """
Run a command inside the Python environment. Run a command inside the Python environment.
""" """
...@@ -1093,9 +1096,7 @@ class Env(object): ...@@ -1093,9 +1096,7 @@ class Env(object):
return decode(output) return decode(output)
def execute( def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
self, bin, *args, **kwargs
): # type: (str, *str, **Any) -> Optional[int]
bin = self._bin(bin) bin = self._bin(bin)
if not self._is_windows: if not self._is_windows:
...@@ -1109,11 +1110,11 @@ class Env(object): ...@@ -1109,11 +1110,11 @@ class Env(object):
exe.communicate() exe.communicate()
return exe.returncode return exe.returncode
def is_venv(self): # type: () -> bool def is_venv(self) -> bool:
raise NotImplementedError() raise NotImplementedError()
@property @property
def script_dirs(self): # type: () -> List[Path] def script_dirs(self) -> List[Path]:
if self._script_dirs is None: if self._script_dirs is None:
self._script_dirs = ( self._script_dirs = (
[Path(self.paths["scripts"])] [Path(self.paths["scripts"])]
...@@ -1124,7 +1125,7 @@ class Env(object): ...@@ -1124,7 +1125,7 @@ class Env(object):
self._script_dirs.append(self.userbase / self._script_dirs[0].name) self._script_dirs.append(self.userbase / self._script_dirs[0].name)
return self._script_dirs return self._script_dirs
def _bin(self, bin): # type: (str) -> str def _bin(self, bin: str) -> str:
""" """
Return path to the given executable. Return path to the given executable.
""" """
...@@ -1147,10 +1148,10 @@ class Env(object): ...@@ -1147,10 +1148,10 @@ class Env(object):
return str(bin_path) return str(bin_path)
def __eq__(self, other): # type: (Env) -> bool def __eq__(self, other: "Env") -> bool:
return other.__class__ == self.__class__ and other.path == self.path return other.__class__ == self.__class__ and other.path == self.path
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return '{}("{}")'.format(self.__class__.__name__, self._path) return '{}("{}")'.format(self.__class__.__name__, self._path)
...@@ -1160,25 +1161,25 @@ class SystemEnv(Env): ...@@ -1160,25 +1161,25 @@ class SystemEnv(Env):
""" """
@property @property
def python(self): # type: () -> str def python(self) -> str:
return sys.executable return sys.executable
@property @property
def sys_path(self): # type: () -> List[str] def sys_path(self) -> List[str]:
return sys.path return sys.path
def get_version_info(self): # type: () -> Tuple[int] def get_version_info(self) -> Tuple[int]:
return sys.version_info return sys.version_info
def get_python_implementation(self): # type: () -> str def get_python_implementation(self) -> str:
return platform.python_implementation() return platform.python_implementation()
def get_pip_command(self): # type: () -> List[str] def get_pip_command(self) -> List[str]:
# If we're not in a venv, assume the interpreter we're running on # If we're not in a venv, assume the interpreter we're running on
# has a pip and use that # has a pip and use that
return [sys.executable, "-m", "pip"] return [sys.executable, "-m", "pip"]
def get_paths(self): # type: () -> Dict[str, str] def get_paths(self) -> Dict[str, str]:
# We can't use sysconfig.get_paths() because # We can't use sysconfig.get_paths() because
# on some distributions it does not return the proper paths # on some distributions it does not return the proper paths
# (those used by pip for instance). We go through distutils # (those used by pip for instance). We go through distutils
...@@ -1207,10 +1208,10 @@ class SystemEnv(Env): ...@@ -1207,10 +1208,10 @@ class SystemEnv(Env):
return paths return paths
def get_supported_tags(self): # type: () -> List[Tag] def get_supported_tags(self) -> List[Tag]:
return list(sys_tags()) return list(sys_tags())
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self) -> Dict[str, Any]:
if hasattr(sys, "implementation"): if hasattr(sys, "implementation"):
info = sys.implementation.version info = sys.implementation.version
iver = "{0.major}.{0.minor}.{0.micro}".format(info) iver = "{0.major}.{0.minor}.{0.micro}".format(info)
...@@ -1243,12 +1244,12 @@ class SystemEnv(Env): ...@@ -1243,12 +1244,12 @@ class SystemEnv(Env):
"interpreter_version": interpreter_version(), "interpreter_version": interpreter_version(),
} }
def get_pip_version(self): # type: () -> Version def get_pip_version(self) -> Version:
from pip import __version__ from pip import __version__
return Version.parse(__version__) return Version.parse(__version__)
def is_venv(self): # type: () -> bool def is_venv(self) -> bool:
return self._path != self._base return self._path != self._base
...@@ -1257,7 +1258,7 @@ class VirtualEnv(Env): ...@@ -1257,7 +1258,7 @@ class VirtualEnv(Env):
A virtual Python environment. A virtual Python environment.
""" """
def __init__(self, path, base=None): # type: (Path, Optional[Path]) -> None def __init__(self, path: Path, base: Optional[Path] = None) -> None:
super(VirtualEnv, self).__init__(path, base) super(VirtualEnv, self).__init__(path, base)
# If base is None, it probably means this is # If base is None, it probably means this is
...@@ -1268,25 +1269,25 @@ class VirtualEnv(Env): ...@@ -1268,25 +1269,25 @@ class VirtualEnv(Env):
self._base = Path(self.run("python", "-", input_=GET_BASE_PREFIX).strip()) self._base = Path(self.run("python", "-", input_=GET_BASE_PREFIX).strip())
@property @property
def sys_path(self): # type: () -> List[str] def sys_path(self) -> List[str]:
output = self.run("python", "-", input_=GET_SYS_PATH) output = self.run("python", "-", input_=GET_SYS_PATH)
return json.loads(output) return json.loads(output)
def get_version_info(self): # type: () -> Tuple[int] def get_version_info(self) -> Tuple[int]:
output = self.run("python", "-", input_=GET_PYTHON_VERSION) output = self.run("python", "-", input_=GET_PYTHON_VERSION)
return tuple([int(s) for s in output.strip().split(".")]) return tuple([int(s) for s in output.strip().split(".")])
def get_python_implementation(self): # type: () -> str def get_python_implementation(self) -> str:
return self.marker_env["platform_python_implementation"] return self.marker_env["platform_python_implementation"]
def get_pip_command(self): # type: () -> List[str] def get_pip_command(self) -> List[str]:
# We're in a virtualenv that is known to be sane, # We're in a virtualenv that is known to be sane,
# so assume that we have a functional pip # so assume that we have a functional pip
return [self._bin("pip")] return [self._bin("pip")]
def get_supported_tags(self): # type: () -> List[Tag] def get_supported_tags(self) -> List[Tag]:
file_path = Path(packaging.tags.__file__) file_path = Path(packaging.tags.__file__)
if file_path.suffix == ".pyc": if file_path.suffix == ".pyc":
# Python 2 # Python 2
...@@ -1316,12 +1317,12 @@ class VirtualEnv(Env): ...@@ -1316,12 +1317,12 @@ class VirtualEnv(Env):
return [Tag(*t) for t in json.loads(output)] return [Tag(*t) for t in json.loads(output)]
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self) -> Dict[str, Any]:
output = self.run("python", "-", input_=GET_ENVIRONMENT_INFO) output = self.run("python", "-", input_=GET_ENVIRONMENT_INFO)
return json.loads(output) return json.loads(output)
def get_pip_version(self): # type: () -> Version def get_pip_version(self) -> Version:
output = self.run_pip("--version").strip() output = self.run_pip("--version").strip()
m = re.match("pip (.+?)(?: from .+)?$", output) m = re.match("pip (.+?)(?: from .+)?$", output)
if not m: if not m:
...@@ -1329,19 +1330,19 @@ class VirtualEnv(Env): ...@@ -1329,19 +1330,19 @@ class VirtualEnv(Env):
return Version.parse(m.group(1)) return Version.parse(m.group(1))
def get_paths(self): # type: () -> Dict[str, str] def get_paths(self) -> Dict[str, str]:
output = self.run("python", "-", input_=GET_PATHS) output = self.run("python", "-", input_=GET_PATHS)
return json.loads(output) return json.loads(output)
def is_venv(self): # type: () -> bool def is_venv(self) -> bool:
return True return True
def is_sane(self): # type: () -> bool def is_sane(self) -> bool:
# A virtualenv is considered sane if both "python" and "pip" exist. # A virtualenv is considered sane if both "python" and "pip" exist.
return os.path.exists(self.python) and os.path.exists(self._bin("pip")) return os.path.exists(self.python) and os.path.exists(self._bin("pip"))
def _run(self, cmd, **kwargs): # type: (List[str], **Any) -> Optional[int] def _run(self, cmd: List[str], **kwargs: Any) -> Optional[int]:
with self.temp_environ(): with self.temp_environ():
os.environ["PATH"] = self._updated_path() os.environ["PATH"] = self._updated_path()
os.environ["VIRTUAL_ENV"] = str(self._path) os.environ["VIRTUAL_ENV"] = str(self._path)
...@@ -1351,9 +1352,7 @@ class VirtualEnv(Env): ...@@ -1351,9 +1352,7 @@ class VirtualEnv(Env):
return super(VirtualEnv, self)._run(cmd, **kwargs) return super(VirtualEnv, self)._run(cmd, **kwargs)
def execute( def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
self, bin, *args, **kwargs
): # type: (str, *str, **Any) -> Optional[int]
with self.temp_environ(): with self.temp_environ():
os.environ["PATH"] = self._updated_path() os.environ["PATH"] = self._updated_path()
os.environ["VIRTUAL_ENV"] = str(self._path) os.environ["VIRTUAL_ENV"] = str(self._path)
...@@ -1364,7 +1363,7 @@ class VirtualEnv(Env): ...@@ -1364,7 +1363,7 @@ class VirtualEnv(Env):
return super(VirtualEnv, self).execute(bin, *args, **kwargs) return super(VirtualEnv, self).execute(bin, *args, **kwargs)
@contextmanager @contextmanager
def temp_environ(self): # type: () -> Iterator[None] def temp_environ(self) -> Iterator[None]:
environ = dict(os.environ) environ = dict(os.environ)
try: try:
yield yield
...@@ -1372,18 +1371,18 @@ class VirtualEnv(Env): ...@@ -1372,18 +1371,18 @@ class VirtualEnv(Env):
os.environ.clear() os.environ.clear()
os.environ.update(environ) os.environ.update(environ)
def unset_env(self, key): # type: (str) -> None def unset_env(self, key: str) -> None:
if key in os.environ: if key in os.environ:
del os.environ[key] del os.environ[key]
def _updated_path(self): # type: () -> str def _updated_path(self) -> str:
return os.pathsep.join([str(self._bin_dir), os.environ.get("PATH", "")]) return os.pathsep.join([str(self._bin_dir), os.environ.get("PATH", "")])
class NullEnv(SystemEnv): class NullEnv(SystemEnv):
def __init__( def __init__(
self, path=None, base=None, execute=False self, path: Path = None, base: Optional[Path] = None, execute: bool = False
): # type: (Path, Optional[Path], bool) -> None ) -> None:
if path is None: if path is None:
path = Path(sys.prefix) path = Path(sys.prefix)
...@@ -1392,40 +1391,38 @@ class NullEnv(SystemEnv): ...@@ -1392,40 +1391,38 @@ class NullEnv(SystemEnv):
self._execute = execute self._execute = execute
self.executed = [] self.executed = []
def get_pip_command(self): # type: () -> List[str] def get_pip_command(self) -> List[str]:
return [self._bin("python"), "-m", "pip"] return [self._bin("python"), "-m", "pip"]
def _run(self, cmd, **kwargs): # type: (List[str], **Any) -> int def _run(self, cmd: List[str], **kwargs: Any) -> int:
self.executed.append(cmd) self.executed.append(cmd)
if self._execute: if self._execute:
return super(NullEnv, self)._run(cmd, **kwargs) return super(NullEnv, self)._run(cmd, **kwargs)
def execute( def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
self, bin, *args, **kwargs
): # type: (str, *str, **Any) -> Optional[int]
self.executed.append([bin] + list(args)) self.executed.append([bin] + list(args))
if self._execute: if self._execute:
return super(NullEnv, self).execute(bin, *args, **kwargs) return super(NullEnv, self).execute(bin, *args, **kwargs)
def _bin(self, bin): # type: (str) -> str def _bin(self, bin: str) -> str:
return bin return bin
class MockEnv(NullEnv): class MockEnv(NullEnv):
def __init__( def __init__(
self, self,
version_info=(3, 7, 0), # type: Tuple[int, int, int] version_info: Tuple[int, int, int] = (3, 7, 0),
python_implementation="CPython", # type: str python_implementation: str = "CPython",
platform="darwin", # type: str platform: str = "darwin",
os_name="posix", # type: str os_name: str = "posix",
is_venv=False, # type: bool is_venv: bool = False,
pip_version="19.1", # type: str pip_version: str = "19.1",
sys_path=None, # type: Optional[List[str]] sys_path: Optional[List[str]] = None,
marker_env=None, # type: Dict[str, Any] marker_env: Dict[str, Any] = None,
supported_tags=None, # type: List[Tag] supported_tags: List[Tag] = None,
**kwargs, # type: Any **kwargs: Any,
): ):
super(MockEnv, self).__init__(**kwargs) super(MockEnv, self).__init__(**kwargs)
...@@ -1440,25 +1437,25 @@ class MockEnv(NullEnv): ...@@ -1440,25 +1437,25 @@ class MockEnv(NullEnv):
self._supported_tags = supported_tags self._supported_tags = supported_tags
@property @property
def platform(self): # type: () -> str def platform(self) -> str:
return self._platform return self._platform
@property @property
def os(self): # type: () -> str def os(self) -> str:
return self._os_name return self._os_name
@property @property
def pip_version(self): # type: () -> Version def pip_version(self) -> Version:
return self._pip_version return self._pip_version
@property @property
def sys_path(self): # type: () -> List[str] def sys_path(self) -> List[str]:
if self._sys_path is None: if self._sys_path is None:
return super(MockEnv, self).sys_path return super(MockEnv, self).sys_path
return self._sys_path return self._sys_path
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self) -> Dict[str, Any]:
if self._mock_marker_env is not None: if self._mock_marker_env is not None:
return self._mock_marker_env return self._mock_marker_env
...@@ -1475,5 +1472,5 @@ class MockEnv(NullEnv): ...@@ -1475,5 +1472,5 @@ class MockEnv(NullEnv):
return marker_env return marker_env
def is_venv(self): # type: () -> bool def is_venv(self) -> bool:
return self._is_venv return self._is_venv
...@@ -21,19 +21,19 @@ class Exporter(object): ...@@ -21,19 +21,19 @@ class Exporter(object):
ACCEPTED_FORMATS = (FORMAT_REQUIREMENTS_TXT,) ACCEPTED_FORMATS = (FORMAT_REQUIREMENTS_TXT,)
ALLOWED_HASH_ALGORITHMS = ("sha256", "sha384", "sha512") ALLOWED_HASH_ALGORITHMS = ("sha256", "sha384", "sha512")
def __init__(self, poetry): # type: (Poetry) -> None def __init__(self, poetry: Poetry) -> None:
self._poetry = poetry self._poetry = poetry
def export( def export(
self, self,
fmt, fmt: str,
cwd, cwd: Path,
output, output: Union[IO, str],
with_hashes=True, with_hashes: bool = True,
dev=False, dev: bool = False,
extras=None, extras: Optional[Union[bool, Sequence[str]]] = None,
with_credentials=False, with_credentials: bool = False,
): # type: (str, Path, Union[IO, str], bool, bool, Optional[Union[bool, Sequence[str]]], bool) -> None ) -> None:
if fmt not in self.ACCEPTED_FORMATS: if fmt not in self.ACCEPTED_FORMATS:
raise ValueError("Invalid export format: {}".format(fmt)) raise ValueError("Invalid export format: {}".format(fmt))
...@@ -48,13 +48,13 @@ class Exporter(object): ...@@ -48,13 +48,13 @@ class Exporter(object):
def _export_requirements_txt( def _export_requirements_txt(
self, self,
cwd, cwd: Path,
output, output: Union[IO, str],
with_hashes=True, with_hashes: bool = True,
dev=False, dev: bool = False,
extras=None, extras: Optional[Union[bool, Sequence[str]]] = None,
with_credentials=False, with_credentials: bool = False,
): # type: (Path, Union[IO, str], bool, bool, Optional[Union[bool, Sequence[str]]], bool) -> None ) -> None:
indexes = set() indexes = set()
content = "" content = ""
dependency_lines = set() dependency_lines = set()
...@@ -150,9 +150,7 @@ class Exporter(object): ...@@ -150,9 +150,7 @@ class Exporter(object):
self._output(content, cwd, output) self._output(content, cwd, output)
def _output( def _output(self, content: str, cwd: Path, output: Union[IO, str]) -> None:
self, content, cwd, output
): # type: (str, Path, Union[IO, str]) -> None
decoded = decode(content) decoded = decode(content)
try: try:
output.write(decoded) output.write(decoded)
......
...@@ -9,10 +9,10 @@ from poetry.utils.helpers import canonicalize_name ...@@ -9,10 +9,10 @@ from poetry.utils.helpers import canonicalize_name
def get_extra_package_names( def get_extra_package_names(
packages, # type: Sequence[Package] packages: Sequence[Package],
extras, # type: Mapping[str, List[str]] extras: Mapping[str, List[str]],
extra_names, # type: Sequence[str] extra_names: Sequence[str],
): # type: (...) -> Iterator[str] ) -> Iterator[str]:
""" """
Returns all package names required by the given extras. Returns all package names required by the given extras.
...@@ -37,7 +37,7 @@ def get_extra_package_names( ...@@ -37,7 +37,7 @@ def get_extra_package_names(
# keep record of packages seen during recursion in order to avoid recursion error # keep record of packages seen during recursion in order to avoid recursion error
seen_package_names = set() seen_package_names = set()
def _extra_packages(package_names): # type: (Iterable[str]) -> Iterator[str] def _extra_packages(package_names: Iterable[str]) -> Iterator[str]:
"""Recursively find dependencies for packages names""" """Recursively find dependencies for packages names"""
# for each extra pacakge name # for each extra pacakge name
for package_name in package_names: for package_name in package_names:
......
...@@ -29,25 +29,25 @@ except ImportError: ...@@ -29,25 +29,25 @@ except ImportError:
_canonicalize_regex = re.compile("[-_]+") _canonicalize_regex = re.compile("[-_]+")
def canonicalize_name(name): # type: (str) -> str def canonicalize_name(name: str) -> str:
return _canonicalize_regex.sub("-", name).lower() return _canonicalize_regex.sub("-", name).lower()
def module_name(name): # type: (str) -> str def module_name(name: str) -> str:
return canonicalize_name(name).replace(".", "_").replace("-", "_") return canonicalize_name(name).replace(".", "_").replace("-", "_")
def normalize_version(version): # type: (str) -> str def normalize_version(version: str) -> str:
return str(Version(version)) return str(Version(version))
def _del_ro(action, name, exc): # type: (Callable, str, Exception) -> None def _del_ro(action: Callable, name: str, exc: Exception) -> None:
os.chmod(name, stat.S_IWRITE) os.chmod(name, stat.S_IWRITE)
os.remove(name) os.remove(name)
@contextmanager @contextmanager
def temporary_directory(*args, **kwargs): # type: (*Any, **Any) -> Iterator[str] def temporary_directory(*args: Any, **kwargs: Any) -> Iterator[str]:
name = tempfile.mkdtemp(*args, **kwargs) name = tempfile.mkdtemp(*args, **kwargs)
yield name yield name
...@@ -55,7 +55,7 @@ def temporary_directory(*args, **kwargs): # type: (*Any, **Any) -> Iterator[str ...@@ -55,7 +55,7 @@ def temporary_directory(*args, **kwargs): # type: (*Any, **Any) -> Iterator[str
shutil.rmtree(name, onerror=_del_ro) shutil.rmtree(name, onerror=_del_ro)
def get_cert(config, repository_name): # type: (Config, str) -> Optional[Path] def get_cert(config: Config, repository_name: str) -> Optional[Path]:
cert = config.get("certificates.{}.cert".format(repository_name)) cert = config.get("certificates.{}.cert".format(repository_name))
if cert: if cert:
return Path(cert) return Path(cert)
...@@ -63,7 +63,7 @@ def get_cert(config, repository_name): # type: (Config, str) -> Optional[Path] ...@@ -63,7 +63,7 @@ def get_cert(config, repository_name): # type: (Config, str) -> Optional[Path]
return None return None
def get_client_cert(config, repository_name): # type: (Config, str) -> Optional[Path] def get_client_cert(config: Config, repository_name: str) -> Optional[Path]:
client_cert = config.get("certificates.{}.client-cert".format(repository_name)) client_cert = config.get("certificates.{}.client-cert".format(repository_name))
if client_cert: if client_cert:
return Path(client_cert) return Path(client_cert)
...@@ -71,7 +71,7 @@ def get_client_cert(config, repository_name): # type: (Config, str) -> Optional ...@@ -71,7 +71,7 @@ def get_client_cert(config, repository_name): # type: (Config, str) -> Optional
return None return None
def _on_rm_error(func, path, exc_info): # type: (Callable, str, Exception) -> None def _on_rm_error(func: Callable, path: str, exc_info: Exception) -> None:
if not os.path.exists(path): if not os.path.exists(path):
return return
...@@ -79,14 +79,14 @@ def _on_rm_error(func, path, exc_info): # type: (Callable, str, Exception) -> N ...@@ -79,14 +79,14 @@ def _on_rm_error(func, path, exc_info): # type: (Callable, str, Exception) -> N
func(path) func(path)
def safe_rmtree(path): # type: (str) -> None def safe_rmtree(path: str) -> None:
if Path(path).is_symlink(): if Path(path).is_symlink():
return os.unlink(str(path)) return os.unlink(str(path))
shutil.rmtree(path, onerror=_on_rm_error) shutil.rmtree(path, onerror=_on_rm_error)
def merge_dicts(d1, d2): # type: (Dict, Dict) -> None def merge_dicts(d1: Dict, d2: Dict) -> None:
for k, v in d2.items(): for k, v in d2.items():
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], Mapping): if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], Mapping):
merge_dicts(d1[k], d2[k]) merge_dicts(d1[k], d2[k])
...@@ -95,8 +95,11 @@ def merge_dicts(d1, d2): # type: (Dict, Dict) -> None ...@@ -95,8 +95,11 @@ def merge_dicts(d1, d2): # type: (Dict, Dict) -> None
def download_file( def download_file(
url, dest, session=None, chunk_size=1024 url: str,
): # type: (str, str, Optional[requests.Session], int) -> None dest: str,
session: Optional[requests.Session] = None,
chunk_size: int = 1024,
) -> None:
get = requests.get if not session else session.get get = requests.get if not session else session.get
with get(url, stream=True) as response: with get(url, stream=True) as response:
...@@ -109,8 +112,8 @@ def download_file( ...@@ -109,8 +112,8 @@ def download_file(
def get_package_version_display_string( def get_package_version_display_string(
package, root=None package: Package, root: Optional[Path] = None
): # type: (Package, Optional[Path]) -> str ) -> str:
if package.source_type in ["file", "directory"] and root: if package.source_type in ["file", "directory"] and root:
return "{} {}".format( return "{} {}".format(
package.version, package.version,
...@@ -120,11 +123,11 @@ def get_package_version_display_string( ...@@ -120,11 +123,11 @@ def get_package_version_display_string(
return package.full_pretty_version return package.full_pretty_version
def paths_csv(paths): # type: (List[Path]) -> str def paths_csv(paths: List[Path]) -> str:
return ", ".join('"{}"'.format(str(c)) for c in paths) return ", ".join('"{}"'.format(str(c)) for c in paths)
def is_dir_writable(path, create=False): # type: (Path, bool) -> bool def is_dir_writable(path: Path, create: bool = False) -> bool:
try: try:
if not path.exists(): if not path.exists():
if not create: if not create:
......
...@@ -6,7 +6,7 @@ from typing import Optional ...@@ -6,7 +6,7 @@ from typing import Optional
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.config.config import Config # noqa from poetry.config.config import Config
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -22,16 +22,16 @@ class KeyRingError(Exception): ...@@ -22,16 +22,16 @@ class KeyRingError(Exception):
class KeyRing: class KeyRing:
def __init__(self, namespace): # type: (str) -> None def __init__(self, namespace: str) -> None:
self._namespace = namespace self._namespace = namespace
self._is_available = True self._is_available = True
self._check() self._check()
def is_available(self): # type: () -> bool def is_available(self) -> bool:
return self._is_available return self._is_available
def get_password(self, name, username): # type: (str, str) -> Optional[str] def get_password(self, name: str, username: str) -> Optional[str]:
if not self.is_available(): if not self.is_available():
return return
...@@ -47,7 +47,7 @@ class KeyRing: ...@@ -47,7 +47,7 @@ class KeyRing:
"Unable to retrieve the password for {} from the key ring".format(name) "Unable to retrieve the password for {} from the key ring".format(name)
) )
def set_password(self, name, username, password): # type: (str, str, str) -> None def set_password(self, name: str, username: str, password: str) -> None:
if not self.is_available(): if not self.is_available():
return return
...@@ -65,7 +65,7 @@ class KeyRing: ...@@ -65,7 +65,7 @@ class KeyRing:
) )
) )
def delete_password(self, name, username): # type: (str, str) -> None def delete_password(self, name: str, username: str) -> None:
if not self.is_available(): if not self.is_available():
return return
...@@ -81,10 +81,10 @@ class KeyRing: ...@@ -81,10 +81,10 @@ class KeyRing:
"Unable to delete the password for {} from the key ring".format(name) "Unable to delete the password for {} from the key ring".format(name)
) )
def get_entry_name(self, name): # type: (str) -> str def get_entry_name(self, name: str) -> str:
return "{}-{}".format(self._namespace, name) return "{}-{}".format(self._namespace, name)
def _check(self): # type: () -> None def _check(self) -> None:
try: try:
import keyring import keyring
except Exception as e: except Exception as e:
...@@ -120,12 +120,12 @@ class KeyRing: ...@@ -120,12 +120,12 @@ class KeyRing:
class PasswordManager: class PasswordManager:
def __init__(self, config): # type: ("Config") -> None def __init__(self, config: "Config") -> None:
self._config = config self._config = config
self._keyring = None self._keyring = None
@property @property
def keyring(self): # type: () -> KeyRing def keyring(self) -> KeyRing:
if self._keyring is None: if self._keyring is None:
self._keyring = KeyRing("poetry-repository") self._keyring = KeyRing("poetry-repository")
if not self._keyring.is_available(): if not self._keyring.is_available():
...@@ -135,7 +135,7 @@ class PasswordManager: ...@@ -135,7 +135,7 @@ class PasswordManager:
return self._keyring return self._keyring
def set_pypi_token(self, name, token): # type: (str, str) -> None def set_pypi_token(self, name: str, token: str) -> None:
if not self.keyring.is_available(): if not self.keyring.is_available():
self._config.auth_config_source.add_property( self._config.auth_config_source.add_property(
"pypi-token.{}".format(name), token "pypi-token.{}".format(name), token
...@@ -143,13 +143,13 @@ class PasswordManager: ...@@ -143,13 +143,13 @@ class PasswordManager:
else: else:
self.keyring.set_password(name, "__token__", token) self.keyring.set_password(name, "__token__", token)
def get_pypi_token(self, name): # type: (str) -> str def get_pypi_token(self, name: str) -> str:
if not self.keyring.is_available(): if not self.keyring.is_available():
return self._config.get("pypi-token.{}".format(name)) return self._config.get("pypi-token.{}".format(name))
return self.keyring.get_password(name, "__token__") return self.keyring.get_password(name, "__token__")
def delete_pypi_token(self, name): # type: (str) -> None def delete_pypi_token(self, name: str) -> None:
if not self.keyring.is_available(): if not self.keyring.is_available():
return self._config.auth_config_source.remove_property( return self._config.auth_config_source.remove_property(
"pypi-token.{}".format(name) "pypi-token.{}".format(name)
...@@ -157,7 +157,7 @@ class PasswordManager: ...@@ -157,7 +157,7 @@ class PasswordManager:
self.keyring.delete_password(name, "__token__") self.keyring.delete_password(name, "__token__")
def get_http_auth(self, name): # type: (str) -> Optional[Dict[str, str]] def get_http_auth(self, name: str) -> Optional[Dict[str, str]]:
auth = self._config.get("http-basic.{}".format(name)) auth = self._config.get("http-basic.{}".format(name))
if not auth: if not auth:
username = self._config.get("http-basic.{}.username".format(name)) username = self._config.get("http-basic.{}.username".format(name))
...@@ -174,9 +174,7 @@ class PasswordManager: ...@@ -174,9 +174,7 @@ class PasswordManager:
"password": password, "password": password,
} }
def set_http_password( def set_http_password(self, name: str, username: str, password: str) -> None:
self, name, username, password
): # type: (str, str, str) -> None
auth = {"username": username} auth = {"username": username}
if not self.keyring.is_available(): if not self.keyring.is_available():
...@@ -186,7 +184,7 @@ class PasswordManager: ...@@ -186,7 +184,7 @@ class PasswordManager:
self._config.auth_config_source.add_property("http-basic.{}".format(name), auth) self._config.auth_config_source.add_property("http-basic.{}".format(name), auth)
def delete_http_password(self, name): # type: (str) -> None def delete_http_password(self, name: str) -> None:
auth = self.get_http_auth(name) auth = self.get_http_auth(name)
if not auth or "username" not in auth: if not auth or "username" not in auth:
return return
......
...@@ -30,8 +30,8 @@ class SetupReader(object): ...@@ -30,8 +30,8 @@ class SetupReader(object):
@classmethod @classmethod
def read_from_directory( def read_from_directory(
cls, directory cls, directory: Union[str, Path]
): # type: (Union[str, Path]) -> Dict[str, Union[List, Dict]] ) -> Dict[str, Union[List, Dict]]:
if isinstance(directory, str): if isinstance(directory, str):
directory = Path(directory) directory = Path(directory)
...@@ -51,9 +51,7 @@ class SetupReader(object): ...@@ -51,9 +51,7 @@ class SetupReader(object):
return result return result
def read_setup_py( def read_setup_py(self, filepath: Union[str, Path]) -> Dict[str, Union[List, Dict]]:
self, filepath
): # type: (Union[str, Path]) -> Dict[str, Union[List, Dict]]
if isinstance(filepath, str): if isinstance(filepath, str):
filepath = Path(filepath) filepath = Path(filepath)
...@@ -80,8 +78,8 @@ class SetupReader(object): ...@@ -80,8 +78,8 @@ class SetupReader(object):
return result return result
def read_setup_cfg( def read_setup_cfg(
self, filepath self, filepath: Union[str, Path]
): # type: (Union[str, Path]) -> Dict[str, Union[List, Dict]] ) -> Dict[str, Union[List, Dict]]:
parser = ConfigParser() parser = ConfigParser()
parser.read(str(filepath)) parser.read(str(filepath))
...@@ -129,8 +127,8 @@ class SetupReader(object): ...@@ -129,8 +127,8 @@ class SetupReader(object):
} }
def _find_setup_call( def _find_setup_call(
self, elements self, elements: List[Any]
): # type: (List[Any]) -> Tuple[Optional[ast.Call], Optional[List[Any]]] ) -> Tuple[Optional[ast.Call], Optional[List[Any]]]:
funcdefs = [] funcdefs = []
for i, element in enumerate(elements): for i, element in enumerate(elements):
if isinstance(element, ast.If) and i == len(elements) - 1: if isinstance(element, ast.If) and i == len(elements) - 1:
...@@ -178,8 +176,8 @@ class SetupReader(object): ...@@ -178,8 +176,8 @@ class SetupReader(object):
return self._find_sub_setup_call(funcdefs) return self._find_sub_setup_call(funcdefs)
def _find_sub_setup_call( def _find_sub_setup_call(
self, elements self, elements: List[Any]
): # type: (List[Any]) -> Tuple[Optional[ast.Call], Optional[List[Any]]] ) -> Tuple[Optional[ast.Call], Optional[List[Any]]]:
for element in elements: for element in elements:
if not isinstance(element, (ast.FunctionDef, ast.If)): if not isinstance(element, (ast.FunctionDef, ast.If)):
continue continue
...@@ -194,9 +192,7 @@ class SetupReader(object): ...@@ -194,9 +192,7 @@ class SetupReader(object):
return None, None return None, None
def _find_install_requires( def _find_install_requires(self, call: ast.Call, body: Iterable[Any]) -> List[str]:
self, call, body
): # type: (ast.Call, Iterable[Any]) -> List[str]
install_requires = [] install_requires = []
value = self._find_in_call(call, "install_requires") value = self._find_in_call(call, "install_requires")
if value is None: if value is None:
...@@ -237,8 +233,8 @@ class SetupReader(object): ...@@ -237,8 +233,8 @@ class SetupReader(object):
return install_requires return install_requires
def _find_extras_require( def _find_extras_require(
self, call, body self, call: ast.Call, body: Iterable[Any]
): # type: (ast.Call, Iterable[Any]) -> Dict[str, List] ) -> Dict[str, List]:
extras_require = {} extras_require = {}
value = self._find_in_call(call, "extras_require") value = self._find_in_call(call, "extras_require")
if value is None: if value is None:
...@@ -289,8 +285,8 @@ class SetupReader(object): ...@@ -289,8 +285,8 @@ class SetupReader(object):
return extras_require return extras_require
def _find_single_string( def _find_single_string(
self, call, body, name self, call: ast.Call, body: List[Any], name: str
): # type: (ast.Call, List[Any], str) -> Optional[str] ) -> Optional[str]:
value = self._find_in_call(call, name) value = self._find_in_call(call, name)
if value is None: if value is None:
# Trying to find in kwargs # Trying to find in kwargs
...@@ -325,12 +321,12 @@ class SetupReader(object): ...@@ -325,12 +321,12 @@ class SetupReader(object):
if variable is not None and isinstance(variable, ast.Str): if variable is not None and isinstance(variable, ast.Str):
return variable.s return variable.s
def _find_in_call(self, call, name): # type: (ast.Call, str) -> Optional[Any] def _find_in_call(self, call: ast.Call, name: str) -> Optional[Any]:
for keyword in call.keywords: for keyword in call.keywords:
if keyword.arg == name: if keyword.arg == name:
return keyword.value return keyword.value
def _find_call_kwargs(self, call): # type: (ast.Call) -> Optional[Any] def _find_call_kwargs(self, call: ast.Call) -> Optional[Any]:
kwargs = None kwargs = None
for keyword in call.keywords: for keyword in call.keywords:
if keyword.arg is None: if keyword.arg is None:
...@@ -338,9 +334,7 @@ class SetupReader(object): ...@@ -338,9 +334,7 @@ class SetupReader(object):
return kwargs return kwargs
def _find_variable_in_body( def _find_variable_in_body(self, body: Iterable[Any], name: str) -> Optional[Any]:
self, body, name
): # type: (Iterable[Any], str) -> Optional[Any]
found = None found = None
for elem in body: for elem in body:
if found: if found:
...@@ -357,8 +351,8 @@ class SetupReader(object): ...@@ -357,8 +351,8 @@ class SetupReader(object):
return elem.value return elem.value
def _find_in_dict( def _find_in_dict(
self, dict_, name self, dict_: Union[ast.Dict, ast.Call], name: str
): # type: (Union[ast.Dict, ast.Call], str) -> Optional[Any] ) -> Optional[Any]:
for key, val in zip(dict_.keys, dict_.values): for key, val in zip(dict_.keys, dict_.values):
if isinstance(key, ast.Str) and key.s == name: if isinstance(key, ast.Str) and key.s == name:
return val return val
...@@ -22,20 +22,20 @@ class Shell: ...@@ -22,20 +22,20 @@ class Shell:
_shell = None _shell = None
def __init__(self, name, path): # type: (str, str) -> None def __init__(self, name: str, path: str) -> None:
self._name = name self._name = name
self._path = path self._path = path
@property @property
def name(self): # type: () -> str def name(self) -> str:
return self._name return self._name
@property @property
def path(self): # type: () -> str def path(self) -> str:
return self._path return self._path
@classmethod @classmethod
def get(cls): # type: () -> Shell def get(cls) -> "Shell":
""" """
Retrieve the current shell. Retrieve the current shell.
""" """
...@@ -61,7 +61,7 @@ class Shell: ...@@ -61,7 +61,7 @@ class Shell:
return cls._shell return cls._shell
def activate(self, env): # type: (VirtualEnv) -> None def activate(self, env: VirtualEnv) -> None:
if WINDOWS: if WINDOWS:
return env.execute(self.path) return env.execute(self.path)
...@@ -79,7 +79,7 @@ class Shell: ...@@ -79,7 +79,7 @@ class Shell:
activate_path = env.path / bin_dir / activate_script activate_path = env.path / bin_dir / activate_script
c.sendline("{} {}".format(self._get_source_command(), activate_path)) c.sendline("{} {}".format(self._get_source_command(), activate_path))
def resize(sig, data): # type: (Any, Any) -> None def resize(sig: Any, data: Any) -> None:
terminal = Terminal() terminal = Terminal()
c.setwinsize(terminal.height, terminal.width) c.setwinsize(terminal.height, terminal.width)
...@@ -91,7 +91,7 @@ class Shell: ...@@ -91,7 +91,7 @@ class Shell:
sys.exit(c.exitstatus) sys.exit(c.exitstatus)
def _get_activate_script(self): # type: () -> str def _get_activate_script(self) -> str:
if "fish" == self._name: if "fish" == self._name:
suffix = ".fish" suffix = ".fish"
elif "csh" == self._name: elif "csh" == self._name:
...@@ -103,7 +103,7 @@ class Shell: ...@@ -103,7 +103,7 @@ class Shell:
return "activate" + suffix return "activate" + suffix
def _get_source_command(self): # type: () -> str def _get_source_command(self) -> str:
if "fish" == self._name: if "fish" == self._name:
return "source" return "source"
elif "csh" == self._name: elif "csh" == self._name:
...@@ -113,5 +113,5 @@ class Shell: ...@@ -113,5 +113,5 @@ class Shell:
return "." return "."
def __repr__(self): # type: () -> str def __repr__(self) -> str:
return '{}("{}", "{}")'.format(self.__class__.__name__, self._name, self._path) return '{}("{}", "{}")'.format(self.__class__.__name__, self._name, self._path)
...@@ -7,20 +7,20 @@ from poetry.core.semver import Version ...@@ -7,20 +7,20 @@ from poetry.core.semver import Version
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.repositories import Pool # noqa from poetry.repositories import Pool
class VersionSelector(object): class VersionSelector(object):
def __init__(self, pool): # type: ("Pool") -> None def __init__(self, pool: "Pool") -> None:
self._pool = pool self._pool = pool
def find_best_candidate( def find_best_candidate(
self, self,
package_name, # type: str package_name: str,
target_package_version=None, # type: Optional[str] target_package_version: Optional[str] = None,
allow_prereleases=False, # type: bool allow_prereleases: bool = False,
source=None, # type: Optional[str] source: Optional[str] = None,
): # type: (...) -> Union[Package, bool] ) -> Union[Package, bool]:
""" """
Given a package name and optional version, Given a package name and optional version,
returns the latest Package that matches returns the latest Package that matches
...@@ -58,12 +58,12 @@ class VersionSelector(object): ...@@ -58,12 +58,12 @@ class VersionSelector(object):
return False return False
return package return package
def find_recommended_require_version(self, package): # type: (Package) -> str def find_recommended_require_version(self, package: Package) -> str:
version = package.version version = package.version
return self._transform_version(version.text, package.pretty_version) return self._transform_version(version.text, package.pretty_version)
def _transform_version(self, version, pretty_version): # type: (str, str) -> str def _transform_version(self, version: str, pretty_version: str) -> str:
try: try:
parsed = Version.parse(version) parsed = Version.parse(version)
parts = [parsed.major, parsed.minor, parsed.patch] parts = [parsed.major, parsed.minor, parsed.patch]
......
...@@ -34,19 +34,19 @@ from tests.helpers import mock_download ...@@ -34,19 +34,19 @@ from tests.helpers import mock_download
class Config(BaseConfig): class Config(BaseConfig):
def get(self, setting_name, default=None): # type: (str, Any) -> Any def get(self, setting_name: str, default: Any = None) -> Any:
self.merge(self._config_source.config) self.merge(self._config_source.config)
self.merge(self._auth_config_source.config) self.merge(self._auth_config_source.config)
return super(Config, self).get(setting_name, default=default) return super(Config, self).get(setting_name, default=default)
def raw(self): # type: () -> Dict[str, Any] def raw(self) -> Dict[str, Any]:
self.merge(self._config_source.config) self.merge(self._config_source.config)
self.merge(self._auth_config_source.config) self.merge(self._auth_config_source.config)
return super(Config, self).raw() return super(Config, self).raw()
def all(self): # type: () -> Dict[str, Any] def all(self) -> Dict[str, Any]:
self.merge(self._config_source.config) self.merge(self._config_source.config)
self.merge(self._auth_config_source.config) self.merge(self._auth_config_source.config)
......
...@@ -6,8 +6,8 @@ from poetry.core.semver import Version ...@@ -6,8 +6,8 @@ from poetry.core.semver import Version
def build_venv( def build_venv(
path, executable=None, flags=None path: Union[Path, str], executable: Optional[str] = None, flags: bool = None
): # type: (Union[Path,str], Optional[str], bool) -> () ) -> ():
Path(path).mkdir(parents=True, exist_ok=True) Path(path).mkdir(parents=True, exist_ok=True)
......
...@@ -15,7 +15,7 @@ from tests.helpers import get_package ...@@ -15,7 +15,7 @@ from tests.helpers import get_package
@pytest.fixture @pytest.fixture
def source_dir(tmp_path): # type: (...) -> Path def source_dir(tmp_path) -> Path:
cwd = os.getcwd() cwd = os.getcwd()
try: try:
......
...@@ -7,7 +7,7 @@ from tests.helpers import get_package ...@@ -7,7 +7,7 @@ from tests.helpers import get_package
@pytest.fixture @pytest.fixture
def source_dir(tmp_path): # type: (Path) -> Path def source_dir(tmp_path: Path) -> Path:
yield Path(tmp_path.as_posix()) yield Path(tmp_path.as_posix())
......
...@@ -21,22 +21,22 @@ def pep517_metadata_mock(): ...@@ -21,22 +21,22 @@ def pep517_metadata_mock():
@pytest.fixture @pytest.fixture
def demo_sdist(): # type: () -> Path def demo_sdist() -> Path:
return FIXTURE_DIR_BASE / "distributions" / "demo-0.1.0.tar.gz" return FIXTURE_DIR_BASE / "distributions" / "demo-0.1.0.tar.gz"
@pytest.fixture @pytest.fixture
def demo_wheel(): # type: () -> Path def demo_wheel() -> Path:
return FIXTURE_DIR_BASE / "distributions" / "demo-0.1.0-py2.py3-none-any.whl" return FIXTURE_DIR_BASE / "distributions" / "demo-0.1.0-py2.py3-none-any.whl"
@pytest.fixture @pytest.fixture
def source_dir(tmp_path): # type: (Path) -> Path def source_dir(tmp_path: Path) -> Path:
yield Path(tmp_path.as_posix()) yield Path(tmp_path.as_posix())
@pytest.fixture @pytest.fixture
def demo_setup(source_dir): # type: (Path) -> Path def demo_setup(source_dir: Path) -> Path:
setup_py = source_dir / "setup.py" setup_py = source_dir / "setup.py"
setup_py.write_text( setup_py.write_text(
decode( decode(
...@@ -50,7 +50,7 @@ def demo_setup(source_dir): # type: (Path) -> Path ...@@ -50,7 +50,7 @@ def demo_setup(source_dir): # type: (Path) -> Path
@pytest.fixture @pytest.fixture
def demo_setup_cfg(source_dir): # type: (Path) -> Path def demo_setup_cfg(source_dir: Path) -> Path:
setup_cfg = source_dir / "setup.cfg" setup_cfg = source_dir / "setup.cfg"
setup_cfg.write_text( setup_cfg.write_text(
decode( decode(
...@@ -69,7 +69,7 @@ def demo_setup_cfg(source_dir): # type: (Path) -> Path ...@@ -69,7 +69,7 @@ def demo_setup_cfg(source_dir): # type: (Path) -> Path
@pytest.fixture @pytest.fixture
def demo_setup_complex(source_dir): # type: (Path) -> Path def demo_setup_complex(source_dir: Path) -> Path:
setup_py = source_dir / "setup.py" setup_py = source_dir / "setup.py"
setup_py.write_text( setup_py.write_text(
decode( decode(
...@@ -83,7 +83,7 @@ def demo_setup_complex(source_dir): # type: (Path) -> Path ...@@ -83,7 +83,7 @@ def demo_setup_complex(source_dir): # type: (Path) -> Path
@pytest.fixture @pytest.fixture
def demo_setup_complex_pep517_legacy(demo_setup_complex): # type: (Path) -> Path def demo_setup_complex_pep517_legacy(demo_setup_complex: Path) -> Path:
pyproject_toml = demo_setup_complex / "pyproject.toml" pyproject_toml = demo_setup_complex / "pyproject.toml"
pyproject_toml.write_text( pyproject_toml.write_text(
decode("[build-system]\n" 'requires = ["setuptools", "wheel"]') decode("[build-system]\n" 'requires = ["setuptools", "wheel"]')
...@@ -91,7 +91,7 @@ def demo_setup_complex_pep517_legacy(demo_setup_complex): # type: (Path) -> Pat ...@@ -91,7 +91,7 @@ def demo_setup_complex_pep517_legacy(demo_setup_complex): # type: (Path) -> Pat
yield demo_setup_complex yield demo_setup_complex
def demo_check_info(info, requires_dist=None): # type: (PackageInfo, Set[str]) -> None def demo_check_info(info: PackageInfo, requires_dist: Set[str] = None) -> None:
assert info.name == "demo" assert info.name == "demo"
assert info.version == "0.1.0" assert info.version == "0.1.0"
assert info.requires_dist assert info.requires_dist
......
...@@ -47,12 +47,12 @@ class MockEnv(BaseMockEnv): ...@@ -47,12 +47,12 @@ class MockEnv(BaseMockEnv):
@pytest.fixture @pytest.fixture
def env(): # type: () -> MockEnv def env() -> MockEnv:
return MockEnv(path=ENV_DIR) return MockEnv(path=ENV_DIR)
@pytest.fixture @pytest.fixture
def repository(mocker, env): # type: (MockFixture, MockEnv) -> InstalledRepository def repository(mocker: MockFixture, env: MockEnv) -> InstalledRepository:
mocker.patch( mocker.patch(
"poetry.utils._compat.metadata.Distribution.discover", "poetry.utils._compat.metadata.Distribution.discover",
return_value=INSTALLED_RESULTS, return_value=INSTALLED_RESULTS,
...@@ -73,8 +73,8 @@ def repository(mocker, env): # type: (MockFixture, MockEnv) -> InstalledReposit ...@@ -73,8 +73,8 @@ def repository(mocker, env): # type: (MockFixture, MockEnv) -> InstalledReposit
def get_package_from_repository( def get_package_from_repository(
name, repository name: str, repository: InstalledRepository
): # type: (str, InstalledRepository) -> Optional[Package] ) -> Optional[Package]:
for pkg in repository.packages: for pkg in repository.packages:
if pkg.name == name: if pkg.name == name:
return pkg return pkg
......
...@@ -118,8 +118,8 @@ def test_env_get_venv_with_venv_folder_present( ...@@ -118,8 +118,8 @@ def test_env_get_venv_with_venv_folder_present(
def build_venv( def build_venv(
path, executable=None, flags=None path: Union[Path, str], executable: Optional[str] = None, flags: bool = None
): # type: (Union[Path,str], Optional[str], bool) -> () ) -> ():
os.mkdir(str(path)) os.mkdir(str(path))
......
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