Commit 1346497b by finswimmer

fix and add several type hints

parent a106cb21
...@@ -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): def boolean_validator(val): # type: (str) -> bool
return val in {"true", "false", "1", "0"} return val in {"true", "false", "1", "0"}
def boolean_normalizer(val): def boolean_normalizer(val): # type: (str) -> bool
return val in ["true", "1"] return val in ["true", "1"]
...@@ -51,11 +51,11 @@ class Config(object): ...@@ -51,11 +51,11 @@ class Config(object):
self._auth_config_source = DictConfigSource() self._auth_config_source = DictConfigSource()
@property @property
def name(self): def name(self): # type: () -> str
return str(self._file.path) return str(self._file.path)
@property @property
def config(self): def config(self): # type: () -> Dict
return self._config return self._config
@property @property
...@@ -82,7 +82,7 @@ class Config(object): ...@@ -82,7 +82,7 @@ class Config(object):
merge_dicts(self._config, config) merge_dicts(self._config, config)
def all(self): # type: () -> Dict[str, Any] def all(self): # type: () -> Dict[str, Any]
def _all(config, parent_key=""): def _all(config, parent_key=""): # type: (Dict, str) -> Dict
all_ = {} all_ = {}
for key in config: for key in 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 tomlkit import document from tomlkit import document
from tomlkit import table from tomlkit import table
...@@ -9,6 +10,8 @@ from .config_source import ConfigSource ...@@ -9,6 +10,8 @@ from .config_source import ConfigSource
if TYPE_CHECKING: if TYPE_CHECKING:
from tomlkit.toml_document import TOMLDocument # noqa
from poetry.core.toml.file import TOMLFile # noqa from poetry.core.toml.file import TOMLFile # noqa
...@@ -56,7 +59,7 @@ class FileConfigSource(ConfigSource): ...@@ -56,7 +59,7 @@ class FileConfigSource(ConfigSource):
current_config = current_config[key] current_config = current_config[key]
@contextmanager @contextmanager
def secure(self): def secure(self): # type: () -> Generator["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()
......
from .application import Application from .application import Application
def main(): def main(): # type: () -> int
return Application().run() return Application().run()
import sys import sys
from typing import TYPE_CHECKING
from cleo import Application as BaseApplication from cleo import Application as BaseApplication
from poetry.__version__ import __version__ from poetry.__version__ import __version__
...@@ -29,8 +31,12 @@ from .commands.version import VersionCommand ...@@ -29,8 +31,12 @@ from .commands.version import VersionCommand
from .config import ApplicationConfig from .config import ApplicationConfig
if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa
class Application(BaseApplication): class Application(BaseApplication):
def __init__(self): def __init__(self): # type: () -> None
super(Application, self).__init__( super(Application, self).__init__(
"poetry", __version__, config=ApplicationConfig("poetry", __version__) "poetry", __version__, config=ApplicationConfig("poetry", __version__)
) )
...@@ -59,7 +65,7 @@ class Application(BaseApplication): ...@@ -59,7 +65,7 @@ class Application(BaseApplication):
self._preliminary_io.error_line("<fg=yellow>{}</>\n".format(message)) self._preliminary_io.error_line("<fg=yellow>{}</>\n".format(message))
@property @property
def poetry(self): def poetry(self): # type: () -> "Poetry"
from pathlib import Path from pathlib import Path
from poetry.factory import Factory from poetry.factory import Factory
......
...@@ -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): def handle(self): # type: () -> 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): def handle(self): # type: () -> 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
......
...@@ -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): def handle(self): # type: () -> None
from poetry.core.masonry import Builder from poetry.core.masonry import Builder
fmt = "all" fmt = "all"
......
...@@ -11,5 +11,5 @@ class CacheCommand(Command): ...@@ -11,5 +11,5 @@ class CacheCommand(Command):
commands = [CacheClearCommand(), CacheListCommand()] commands = [CacheClearCommand(), CacheListCommand()]
def handle(self): def handle(self): # type: () -> int
return self.call("help", self._config.name) return self.call("help", self._config.name)
...@@ -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): def handle(self): # type: () -> int
from cachy import CacheManager from cachy import CacheManager
from poetry.locations import REPOSITORY_CACHE_DIR from poetry.locations import REPOSITORY_CACHE_DIR
......
import os import os
from typing import Optional
from ..command import Command from ..command import Command
...@@ -8,7 +10,7 @@ class CacheListCommand(Command): ...@@ -8,7 +10,7 @@ class CacheListCommand(Command):
name = "list" name = "list"
description = "List Poetry's caches." description = "List Poetry's caches."
def handle(self): def handle(self): # type: () -> 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): def handle(self): # type: () -> 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
......
from typing import TYPE_CHECKING
from cleo import Command as BaseCommand from cleo import Command as BaseCommand
if TYPE_CHECKING:
from poetry.poetry import Poetry # noqa
class Command(BaseCommand): class Command(BaseCommand):
loggers = [] loggers = []
@property @property
def poetry(self): def poetry(self): # type: () -> "Poetry"
return self.application.poetry return self.application.poetry
def reset_poetry(self): # type: () -> None def reset_poetry(self): # type: () -> None
......
import json import json
import re import re
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
from cleo import argument from cleo import argument
from cleo import option from cleo import option
...@@ -11,6 +18,10 @@ from poetry.factory import Factory ...@@ -11,6 +18,10 @@ from poetry.factory import Factory
from .command import Command from .command import Command
if TYPE_CHECKING:
from poetry.config.config_source import ConfigSource # noqa
class ConfigCommand(Command): class ConfigCommand(Command):
name = "config" name = "config"
...@@ -40,7 +51,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -40,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): def unique_config_values(self): # type: () -> 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
...@@ -75,7 +86,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -75,7 +86,7 @@ To remove a repository (repo is a short alias for repositories):
return unique_config_values return unique_config_values
def handle(self): def handle(self): # type: () -> 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
...@@ -253,7 +264,9 @@ To remove a repository (repo is a short alias for repositories): ...@@ -253,7 +264,9 @@ 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(self, source, key, callbacks, values): def _handle_single_value(
self, source, key, callbacks, values
): # type: ("ConfigSource", str, Tuple[Any, Any, Any], List[Any]) -> int
validator, normalizer, _ = callbacks validator, normalizer, _ = callbacks
if len(values) > 1: if len(values) > 1:
...@@ -267,7 +280,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -267,7 +280,7 @@ To remove a repository (repo is a short alias for repositories):
return 0 return 0
def _list_configuration(self, config, raw, k=""): def _list_configuration(self, config, raw, k=""): # type: (Dict, Dict, 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:
...@@ -301,7 +314,9 @@ To remove a repository (repo is a short alias for repositories): ...@@ -301,7 +314,9 @@ To remove a repository (repo is a short alias for repositories):
self.line(message) self.line(message)
def _get_setting(self, contents, setting=None, k=None, default=None): def _get_setting(
self, contents, setting=None, k=None, default=None
): # type: (Dict, Optional[str], Optional[str], Optional[Any]) -> 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:
......
...@@ -10,7 +10,7 @@ class DebugInfoCommand(Command): ...@@ -10,7 +10,7 @@ class DebugInfoCommand(Command):
name = "info" name = "info"
description = "Shows debug information." description = "Shows debug information."
def handle(self): def handle(self): # type: () -> 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 Optional
from cleo import argument from cleo import argument
from cleo import option from cleo import option
...@@ -27,7 +29,7 @@ class DebugResolveCommand(InitCommand): ...@@ -27,7 +29,7 @@ class DebugResolveCommand(InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): def handle(self): # type: () -> Optional[int]
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
from poetry.factory import Factory from poetry.factory import Factory
from poetry.io.null_io import NullIO from poetry.io.null_io import NullIO
......
from typing import TYPE_CHECKING
from typing import Optional
from cleo import option from cleo import option
from ..command import Command from ..command import Command
if TYPE_CHECKING:
from poetry.utils.env import Env # noqa
class EnvInfoCommand(Command): class EnvInfoCommand(Command):
name = "info" name = "info"
...@@ -10,7 +17,7 @@ class EnvInfoCommand(Command): ...@@ -10,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): def handle(self): # type: () -> Optional[int]
from poetry.utils.env import EnvManager from poetry.utils.env import EnvManager
env = EnvManager(self.poetry).get() env = EnvManager(self.poetry).get()
...@@ -25,7 +32,7 @@ class EnvInfoCommand(Command): ...@@ -25,7 +32,7 @@ class EnvInfoCommand(Command):
self._display_complete_info(env) self._display_complete_info(env)
def _display_complete_info(self, env): def _display_complete_info(self, env): # type: ("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): def handle(self): # type: () -> 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): def handle(self): # type: () -> 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): def handle(self): # type: () -> None
from poetry.utils.env import EnvManager from poetry.utils.env import EnvManager
manager = EnvManager(self.poetry) manager = EnvManager(self.poetry)
......
from typing import TYPE_CHECKING
from .command import Command from .command import Command
if TYPE_CHECKING:
from poetry.utils.env import VirtualEnv # noqa
class EnvCommand(Command): class EnvCommand(Command):
def __init__(self): def __init__(self): # type: () -> None
self._env = None self._env = None
super(EnvCommand, self).__init__() super(EnvCommand, self).__init__()
@property @property
def env(self): def env(self): # type: () -> "VirtualEnv"
return self._env return self._env
def set_env(self, env): def set_env(self, env): # type: ("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): def handle(self): # type: () -> None
fmt = self.option("format") fmt = self.option("format")
if fmt not in Exporter.ACCEPTED_FORMATS: if fmt not in Exporter.ACCEPTED_FORMATS:
......
...@@ -9,6 +9,7 @@ import urllib.parse ...@@ -9,6 +9,7 @@ import urllib.parse
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional
from typing import Tuple from typing import Tuple
from typing import Union from typing import Union
...@@ -56,12 +57,12 @@ class InitCommand(Command): ...@@ -56,12 +57,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): def __init__(self): # type: () -> None
super(InitCommand, self).__init__() super(InitCommand, self).__init__()
self._pool = None self._pool = None
def handle(self): def handle(self): # type: () -> int
from pathlib import Path from pathlib import Path
from poetry.core.vcs.git import GitConfig from poetry.core.vcs.git import GitConfig
...@@ -227,7 +228,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -227,7 +228,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
def _determine_requirements( def _determine_requirements(
self, requires, allow_prereleases=False, source=None self, requires, allow_prereleases=False, source=None
): # type: (List[str], bool) -> List[Dict[str, str]] ): # type: (List[str], bool, Optional[str]) -> List[Dict[str, Union[str, List[str]]]]
if not requires: if not requires:
requires = [] requires = []
...@@ -354,7 +355,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -354,7 +355,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
def _find_best_version_for_package( def _find_best_version_for_package(
self, name, required_version=None, allow_prereleases=False, source=None self, name, required_version=None, allow_prereleases=False, source=None
): # type: (...) -> Tuple[str, str] ): # type: (str, Optional[str], bool, Optional[str]) -> 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())
...@@ -505,7 +506,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -505,7 +506,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): def _validate_author(self, author, default): # type: (str, 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
...@@ -522,7 +523,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -522,7 +523,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return author return author
def _validate_license(self, license): def _validate_license(self, license): # type: (str) -> str
from poetry.core.spdx import license_by_id from poetry.core.spdx import license_by_id
if license: if license:
...@@ -530,7 +531,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the ...@@ -530,7 +531,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
return license return license
def _get_pool(self): def _get_pool(self): # type: () -> "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
......
...@@ -47,7 +47,7 @@ dependencies and not including the current project, run the command with the ...@@ -47,7 +47,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): def handle(self): # type: () -> 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,12 +9,12 @@ if TYPE_CHECKING: ...@@ -9,12 +9,12 @@ if TYPE_CHECKING:
class InstallerCommand(EnvCommand): class InstallerCommand(EnvCommand):
def __init__(self): def __init__(self): # type: () -> None
self._installer = None # type: Optional[Installer] self._installer = None # type: Optional[Installer]
super(InstallerCommand, self).__init__() super(InstallerCommand, self).__init__()
def reset_poetry(self): def reset_poetry(self): # type: () -> 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)
......
...@@ -24,7 +24,7 @@ file. ...@@ -24,7 +24,7 @@ file.
loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self): # type: () -> 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): def handle(self): # type: () -> None
from pathlib import Path from pathlib import Path
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
......
from pathlib import Path from pathlib import Path
from typing import Optional
from cleo import option from cleo import option
...@@ -40,7 +41,7 @@ the config command. ...@@ -40,7 +41,7 @@ the config command.
loggers = ["poetry.masonry.publishing.publisher"] loggers = ["poetry.masonry.publishing.publisher"]
def handle(self): def handle(self): # type: () -> 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): def handle(self): # type: () -> int
packages = self.argument("packages") packages = self.argument("packages")
is_dev = self.option("dev") is_dev = self.option("dev")
......
from typing import Any
from typing import Union
from cleo import argument from cleo import argument
from .env_command import EnvCommand from .env_command import EnvCommand
...@@ -19,7 +22,7 @@ class RunCommand(EnvCommand): ...@@ -19,7 +22,7 @@ class RunCommand(EnvCommand):
self.config.set_args_parser(RunArgsParser()) self.config.set_args_parser(RunArgsParser())
def handle(self): def handle(self): # type: () -> 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")
...@@ -29,7 +32,7 @@ class RunCommand(EnvCommand): ...@@ -29,7 +32,7 @@ class RunCommand(EnvCommand):
return self.env.execute(*args) return self.env.execute(*args)
def run_script(self, script, args): def run_script(self, script, args): # type: (Union[str, dict], 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): def handle(self): # type: () -> 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"))
......
...@@ -9,5 +9,5 @@ class SelfCommand(Command): ...@@ -9,5 +9,5 @@ class SelfCommand(Command):
commands = [SelfUpdateCommand()] commands = [SelfUpdateCommand()]
def handle(self): def handle(self): # type: () -> int
return self.call("help", self._config.name) return self.call("help", self._config.name)
...@@ -11,6 +11,8 @@ import tarfile ...@@ -11,6 +11,8 @@ import tarfile
from functools import cmp_to_key from functools import cmp_to_key
from gzip import GzipFile from gzip import GzipFile
from typing import TYPE_CHECKING
from typing import Any
from cleo import argument from cleo import argument
from cleo import option from cleo import option
...@@ -20,6 +22,12 @@ from poetry.core.packages import Dependency ...@@ -20,6 +22,12 @@ from poetry.core.packages import Dependency
from ..command import Command from ..command import Command
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.semver import Version
from poetry.utils._compat import Path
try: try:
from urllib.error import HTTPError from urllib.error import HTTPError
from urllib.request import urlopen from urllib.request import urlopen
...@@ -61,24 +69,24 @@ class SelfUpdateCommand(Command): ...@@ -61,24 +69,24 @@ class SelfUpdateCommand(Command):
BASE_URL = REPOSITORY_URL + "/releases/download" BASE_URL = REPOSITORY_URL + "/releases/download"
@property @property
def home(self): def home(self): # type: () -> 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): def bin(self): # type: () -> Path
return self.home / "bin" return self.home / "bin"
@property @property
def lib(self): def lib(self): # type: () -> Path
return self.home / "lib" return self.home / "lib"
@property @property
def lib_backup(self): def lib_backup(self): # type: () -> Path
return self.home / "lib-backup" return self.home / "lib-backup"
def handle(self): def handle(self): # type: () -> 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
...@@ -129,7 +137,7 @@ class SelfUpdateCommand(Command): ...@@ -129,7 +137,7 @@ class SelfUpdateCommand(Command):
self.update(release) self.update(release)
def update(self, release): def update(self, release): # type: ("Package") -> None
version = release.version version = release.version
self.line("Updating to <info>{}</info>".format(version)) self.line("Updating to <info>{}</info>".format(version))
...@@ -165,7 +173,7 @@ class SelfUpdateCommand(Command): ...@@ -165,7 +173,7 @@ class SelfUpdateCommand(Command):
) )
) )
def _update(self, version): def _update(self, version): # type: ("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)
...@@ -235,10 +243,10 @@ class SelfUpdateCommand(Command): ...@@ -235,10 +243,10 @@ class SelfUpdateCommand(Command):
finally: finally:
gz.close() gz.close()
def process(self, *args): def process(self, *args): # type: (*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): def _check_recommended_installation(self): # type: () -> None
from pathlib import Path from pathlib import Path
current = Path(__file__) current = Path(__file__)
...@@ -250,14 +258,14 @@ class SelfUpdateCommand(Command): ...@@ -250,14 +258,14 @@ class SelfUpdateCommand(Command):
"Cannot update automatically." "Cannot update automatically."
) )
def _get_release_name(self, version): def _get_release_name(self, version): # type: ("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): def make_bin(self): # type: () -> 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)
...@@ -286,7 +294,7 @@ class SelfUpdateCommand(Command): ...@@ -286,7 +294,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): def _which_python(self): # type: () -> 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): def handle(self): # type: () -> 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
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import TYPE_CHECKING
from typing import List
from typing import Optional
from typing import Union
from cleo import argument from cleo import argument
from cleo import option from cleo import option
from .env_command import EnvCommand from .env_command import EnvCommand
if TYPE_CHECKING:
from clikit.api.io import IO # noqa
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository
class ShowCommand(EnvCommand): class ShowCommand(EnvCommand):
name = "show" name = "show"
...@@ -32,7 +46,7 @@ lists all packages available.""" ...@@ -32,7 +46,7 @@ lists all packages available."""
colors = ["cyan", "yellow", "green", "magenta", "blue"] colors = ["cyan", "yellow", "green", "magenta", "blue"]
def handle(self): def handle(self): # type: () -> Optional[int]
from clikit.utils.terminal import Terminal from clikit.utils.terminal import Terminal
from poetry.io.null_io import NullIO from poetry.io.null_io import NullIO
...@@ -257,7 +271,9 @@ lists all packages available.""" ...@@ -257,7 +271,9 @@ lists all packages available."""
self.line(line) self.line(line)
def display_package_tree(self, io, package, installed_repo): def display_package_tree(
self, io, package, installed_repo
): # type: ("IO", "Package", "Repository") -> 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:
...@@ -294,13 +310,13 @@ lists all packages available.""" ...@@ -294,13 +310,13 @@ lists all packages available."""
def _display_tree( def _display_tree(
self, self,
io, io, # type: "IO"
dependency, dependency, # type: "Dependency"
installed_repo, installed_repo, # type: "Repository"
packages_in_tree, packages_in_tree, # type: List[str]
previous_tree_bar="├", previous_tree_bar="├", # type: str
level=1, level=1, # type: int
): ): # type: (...) -> None
previous_tree_bar = previous_tree_bar.replace("├", "│") previous_tree_bar = previous_tree_bar.replace("├", "│")
dependencies = [] dependencies = []
...@@ -345,7 +361,7 @@ lists all packages available.""" ...@@ -345,7 +361,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): def _write_tree_line(self, io, line): # type: ("IO", str) -> None
if not io.output.supports_ansi(): if not io.output.supports_ansi():
line = line.replace("└", "`-") line = line.replace("└", "`-")
line = line.replace("├", "|-") line = line.replace("├", "|-")
...@@ -354,7 +370,7 @@ lists all packages available.""" ...@@ -354,7 +370,7 @@ lists all packages available."""
io.write_line(line) io.write_line(line)
def init_styles(self, io): def init_styles(self, io): # type: ("IO") -> None
from clikit.api.formatter import Style from clikit.api.formatter import Style
for color in self.colors: for color in self.colors:
...@@ -362,7 +378,9 @@ lists all packages available.""" ...@@ -362,7 +378,9 @@ lists all packages available."""
io.output.formatter.add_style(style) io.output.formatter.add_style(style)
io.error_output.formatter.add_style(style) io.error_output.formatter.add_style(style)
def find_latest_package(self, package, include_dev): def find_latest_package(
self, package, include_dev
): # type: ("Package", bool) -> Union["Package", bool]
from clikit.io import NullIO from clikit.io import NullIO
from poetry.puzzle.provider import Provider from poetry.puzzle.provider import Provider
...@@ -390,7 +408,7 @@ lists all packages available.""" ...@@ -390,7 +408,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): def get_update_status(self, latest, package): # type: ("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:
...@@ -405,7 +423,9 @@ lists all packages available.""" ...@@ -405,7 +423,9 @@ lists all packages available."""
# it needs an upgrade but has potential BC breaks so is not urgent # it needs an upgrade but has potential BC breaks so is not urgent
return "update-possible" return "update-possible"
def get_installed_status(self, locked, installed_repo): def get_installed_status(
self, locked, installed_repo
): # type: ("Package", "InstalledRepository") -> 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): def handle(self): # type: () -> int
packages = self.argument("packages") packages = self.argument("packages")
self._installer.use_executor( self._installer.use_executor(
......
...@@ -40,7 +40,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease. ...@@ -40,7 +40,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease.
"prerelease", "prerelease",
} }
def handle(self): def handle(self): # type: () -> None
version = self.argument("version") version = self.argument("version")
if version: if version:
...@@ -72,7 +72,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease. ...@@ -72,7 +72,7 @@ patch, minor, major, prepatch, preminor, premajor, prerelease.
) )
) )
def increment_version(self, version, rule): def increment_version(self, version, rule): # type: (str, str) -> "Version"
from poetry.core.semver import Version from poetry.core.semver import Version
try: try:
......
...@@ -34,7 +34,7 @@ from poetry.mixology.solutions.providers import PythonRequirementSolutionProvide ...@@ -34,7 +34,7 @@ from poetry.mixology.solutions.providers import PythonRequirementSolutionProvide
class ApplicationConfig(BaseApplicationConfig): class ApplicationConfig(BaseApplicationConfig):
def configure(self): def configure(self): # type: () -> None
super(ApplicationConfig, self).configure() super(ApplicationConfig, self).configure()
self.add_style(Style("c1").fg("cyan")) self.add_style(Style("c1").fg("cyan"))
......
import logging import logging
from typing import TYPE_CHECKING
from .formatters import FORMATTERS from .formatters import FORMATTERS
if TYPE_CHECKING:
from logging import LogRecord # noqa
class IOFormatter(logging.Formatter): class IOFormatter(logging.Formatter):
_colors = { _colors = {
...@@ -12,7 +18,7 @@ class IOFormatter(logging.Formatter): ...@@ -12,7 +18,7 @@ class IOFormatter(logging.Formatter):
"info": "fg=blue", "info": "fg=blue",
} }
def format(self, record): def format(self, record): # type: ("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
......
import logging import logging
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from logging import LogRecord # noqa
from clikit.api.io import IO # noqa
class IOHandler(logging.Handler): class IOHandler(logging.Handler):
def __init__(self, io): def __init__(self, io): # type: ("IO") -> None
self._io = io self._io = io
super(IOHandler, self).__init__() super(IOHandler, self).__init__()
def emit(self, record): def emit(self, record): # type: ("LogRecord") -> None
try: try:
msg = self.format(record) msg = self.format(record)
level = record.levelname.lower() level = record.levelname.lower()
......
...@@ -137,7 +137,7 @@ class Factory(BaseFactory): ...@@ -137,7 +137,7 @@ class Factory(BaseFactory):
def create_legacy_repository( def create_legacy_repository(
self, source, auth_config self, source, auth_config
): # type: (Dict[str, str], Config) -> LegacyRepository ): # type: (Dict[str, str], Config) -> "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
......
...@@ -120,7 +120,7 @@ class PackageInfo: ...@@ -120,7 +120,7 @@ class PackageInfo:
return cls(cache_version=cache_version, **data) return cls(cache_version=cache_version, **data)
@classmethod @classmethod
def _log(cls, msg, level="info"): def _log(cls, msg, level="info"): # type: (str, str) -> 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))
...@@ -436,7 +436,7 @@ class PackageInfo: ...@@ -436,7 +436,7 @@ class PackageInfo:
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): # type: (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.
......
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class BaseInstaller: class BaseInstaller:
def install(self, package): def install(self, package): # type: ("Package") -> None
raise NotImplementedError raise NotImplementedError
def update(self, source, target): def update(self, source, target): # type: ("Package", "Package") -> None
raise NotImplementedError raise NotImplementedError
def remove(self, package): def remove(self, package): # type: ("Package") -> None
raise NotImplementedError raise NotImplementedError
import re import re
from typing import List from typing import List
from typing import Optional
from typing import Tuple from typing import Tuple
from packaging.tags import Tag from packaging.tags import Tag
...@@ -34,12 +35,12 @@ class Wheel(object): ...@@ -34,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): def get_minimum_supported_index(self, tags): # type: (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): def is_supported_by_environment(self, env): # type: (Env) -> bool
return bool(set(env.supported_tags).intersection(self.tags)) return bool(set(env.supported_tags).intersection(self.tags))
......
...@@ -9,6 +9,10 @@ from concurrent.futures import ThreadPoolExecutor ...@@ -9,6 +9,10 @@ from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import wait from concurrent.futures import wait
from pathlib import Path from pathlib import Path
from subprocess import CalledProcessError from subprocess import CalledProcessError
from typing import TYPE_CHECKING
from typing import Any
from typing import List
from typing import Union
from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.file_dependency import FileDependency
from poetry.core.packages.utils.link import Link from poetry.core.packages.utils.link import Link
...@@ -27,8 +31,20 @@ from .operations.uninstall import Uninstall ...@@ -27,8 +31,20 @@ from .operations.uninstall import Uninstall
from .operations.update import Update from .operations.update import Update
if TYPE_CHECKING:
from clikit.api.io import IO # noqa
from poetry.config.config import Config # noqa
from poetry.repositories import Pool # noqa
from poetry.utils.env import Env # noqa
from .operations import OperationTypes # noqa
class Executor(object): class Executor(object):
def __init__(self, env, pool, config, io, parallel=None): def __init__(
self, env, pool, config, io, parallel=None
): # type: ("Env", "Pool", "Config", "IO", bool) -> None
self._env = env self._env = env
self._io = io self._io = io
self._dry_run = False self._dry_run = False
...@@ -77,22 +93,22 @@ class Executor(object): ...@@ -77,22 +93,22 @@ class Executor(object):
def supports_fancy_output(self): # type: () -> bool def supports_fancy_output(self): # type: () -> bool
return self._io.supports_ansi() and not self._dry_run return self._io.supports_ansi() and not self._dry_run
def disable(self): def disable(self): # type: () -> "Executor"
self._enabled = False self._enabled = False
return self return self
def dry_run(self, dry_run=True): def dry_run(self, dry_run=True): # type: (bool) -> Executor
self._dry_run = dry_run self._dry_run = dry_run
return self return self
def verbose(self, verbose=True): def verbose(self, verbose=True): # type: (bool) -> Executor
self._verbose = verbose self._verbose = verbose
return self return self
def execute(self, operations): # type: (Operation) -> int def execute(self, operations): # type: (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
...@@ -145,7 +161,7 @@ class Executor(object): ...@@ -145,7 +161,7 @@ class Executor(object):
return 1 if self._shutdown else 0 return 1 if self._shutdown else 0
def _write(self, operation, line): def _write(self, operation, line): # type: ("OperationTypes", 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
): ):
...@@ -163,7 +179,7 @@ class Executor(object): ...@@ -163,7 +179,7 @@ class Executor(object):
section.output.clear() section.output.clear()
section.write(line) section.write(line)
def _execute_operation(self, operation): def _execute_operation(self, operation): # type: ("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:
...@@ -240,7 +256,7 @@ class Executor(object): ...@@ -240,7 +256,7 @@ class Executor(object):
with self._lock: with self._lock:
self._shutdown = True self._shutdown = True
def _do_execute_operation(self, operation): def _do_execute_operation(self, operation): # type: ("OperationTypes") -> int
method = operation.job_type method = operation.job_type
operation_message = self.get_operation_message(operation) operation_message = self.get_operation_message(operation)
...@@ -283,7 +299,9 @@ class Executor(object): ...@@ -283,7 +299,9 @@ class Executor(object):
return result return result
def _increment_operations_count(self, operation, executed): def _increment_operations_count(
self, operation, executed
): # type: ("OperationTypes", bool) -> None
with self._lock: with self._lock:
if executed: if executed:
self._executed_operations += 1 self._executed_operations += 1
...@@ -291,7 +309,7 @@ class Executor(object): ...@@ -291,7 +309,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: (...) -> int def run_pip(self, *args, **kwargs): # type: (*Any, **Any) -> int
try: try:
self._env.run_pip(*args, **kwargs) self._env.run_pip(*args, **kwargs)
except EnvCommandError as e: except EnvCommandError as e:
...@@ -306,7 +324,9 @@ class Executor(object): ...@@ -306,7 +324,9 @@ class Executor(object):
return 0 return 0
def get_operation_message(self, operation, done=False, error=False, warning=False): def get_operation_message(
self, operation, done=False, error=False, warning=False
): # type: ("OperationTypes", bool, bool, bool) -> str
base_tag = "fg=default" base_tag = "fg=default"
operation_color = "c2" operation_color = "c2"
source_operation_color = "c2" source_operation_color = "c2"
...@@ -360,7 +380,7 @@ class Executor(object): ...@@ -360,7 +380,7 @@ class Executor(object):
return "" return ""
def _display_summary(self, operations): def _display_summary(self, operations): # type: (List["OperationTypes"]) -> None
installs = 0 installs = 0
updates = 0 updates = 0
uninstalls = 0 uninstalls = 0
...@@ -403,13 +423,13 @@ class Executor(object): ...@@ -403,13 +423,13 @@ class Executor(object):
) )
self._io.write_line("") self._io.write_line("")
def _execute_install(self, operation): # type: (Install) -> None def _execute_install(self, operation): # type: (Union[Install, Update]) -> int
return self._install(operation) return self._install(operation)
def _execute_update(self, operation): # type: (Update) -> None def _execute_update(self, operation): # type: (Union[Install, Update]) -> int
return self._update(operation) return self._update(operation)
def _execute_uninstall(self, operation): # type: (Uninstall) -> None def _execute_uninstall(self, operation): # type: (Uninstall) -> int
message = " <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format( message = " <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format(
message=self.get_operation_message(operation), message=self.get_operation_message(operation),
) )
...@@ -417,7 +437,7 @@ class Executor(object): ...@@ -417,7 +437,7 @@ class Executor(object):
return self._remove(operation) return self._remove(operation)
def _install(self, operation): def _install(self, operation): # type: (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)
...@@ -444,10 +464,10 @@ class Executor(object): ...@@ -444,10 +464,10 @@ class Executor(object):
return self.run_pip(*args) return self.run_pip(*args)
def _update(self, operation): def _update(self, operation): # type: (Union[Install, Update]) -> int
return self._install(operation) return self._install(operation)
def _remove(self, operation): def _remove(self, operation): # type: (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
...@@ -464,7 +484,7 @@ class Executor(object): ...@@ -464,7 +484,7 @@ class Executor(object):
raise raise
def _prepare_file(self, operation): def _prepare_file(self, operation): # type: (Union[Install, Update]) -> Path
package = operation.package package = operation.package
message = " <fg=blue;options=bold>•</> {message}: <info>Preparing...</info>".format( message = " <fg=blue;options=bold>•</> {message}: <info>Preparing...</info>".format(
...@@ -480,7 +500,7 @@ class Executor(object): ...@@ -480,7 +500,7 @@ class Executor(object):
return archive return archive
def _install_directory(self, operation): def _install_directory(self, operation): # type: (Union[Install, Update]) -> int
from poetry.factory import Factory from poetry.factory import Factory
package = operation.package package = operation.package
...@@ -544,7 +564,7 @@ class Executor(object): ...@@ -544,7 +564,7 @@ class Executor(object):
return self.run_pip(*args) return self.run_pip(*args)
def _install_git(self, operation): def _install_git(self, operation): # type: (Union[Install, Update]) -> int
from poetry.core.vcs import Git from poetry.core.vcs import Git
package = operation.package package = operation.package
...@@ -570,12 +590,14 @@ class Executor(object): ...@@ -570,12 +590,14 @@ class Executor(object):
return self._install_directory(operation) return self._install_directory(operation)
def _download(self, operation): # type: (Operation) -> Path def _download(self, operation): # type: (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(self, operation, link): def _download_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)
...@@ -607,7 +629,9 @@ class Executor(object): ...@@ -607,7 +629,9 @@ class Executor(object):
return archive return archive
def _download_archive(self, operation, link): # type: (Operation, Link) -> Path def _download_archive(
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)
) )
......
from typing import TYPE_CHECKING
from typing import Iterable
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Union from typing import Union
...@@ -23,11 +25,17 @@ from .operations.operation import Operation ...@@ -23,11 +25,17 @@ from .operations.operation import Operation
from .pip_installer import PipInstaller from .pip_installer import PipInstaller
if TYPE_CHECKING:
from poetry.utils.env import Env # noqa
from .operations import OperationTypes # noqa
class Installer: class Installer:
def __init__( def __init__(
self, self,
io, # type: IO io, # type: IO
env, env, # type: "Env"
package, # type: ProjectPackage package, # type: ProjectPackage
locker, # type: Locker locker, # type: Locker
pool, # type: Pool pool, # type: Pool
...@@ -67,11 +75,11 @@ class Installer: ...@@ -67,11 +75,11 @@ class Installer:
self._installed_repository = installed self._installed_repository = installed
@property @property
def executor(self): def executor(self): # type: () -> Executor
return self._executor return self._executor
@property @property
def installer(self): def installer(self): # type: () -> BaseInstaller
return self._installer return self._installer
def set_package(self, package): # type: (ProjectPackage) -> Installer def set_package(self, package): # type: (ProjectPackage) -> Installer
...@@ -84,7 +92,7 @@ class Installer: ...@@ -84,7 +92,7 @@ class Installer:
return self return self
def run(self): def run(self): # type: () -> 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()
...@@ -162,7 +170,7 @@ class Installer: ...@@ -162,7 +170,7 @@ class Installer:
return self return self
def whitelist(self, packages): # type: (dict) -> Installer def whitelist(self, packages): # type: (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
...@@ -177,7 +185,7 @@ class Installer: ...@@ -177,7 +185,7 @@ class Installer:
return self return self
def _do_refresh(self): def _do_refresh(self): # type: () -> int
from poetry.puzzle import Solver from poetry.puzzle import Solver
# Checking extras # Checking extras
...@@ -203,7 +211,7 @@ class Installer: ...@@ -203,7 +211,7 @@ class Installer:
return 0 return 0
def _do_install(self, local_repo): def _do_install(self, local_repo): # type: (Repository) -> int
from poetry.puzzle import Solver from poetry.puzzle import Solver
locked_repository = Repository() locked_repository = Repository()
...@@ -323,7 +331,7 @@ class Installer: ...@@ -323,7 +331,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): def _execute(self, operations): # type: (List["OperationTypes"]) -> int
if self._use_executor: if self._use_executor:
return self._executor.execute(operations) return self._executor.execute(operations)
...@@ -459,7 +467,9 @@ class Installer: ...@@ -459,7 +467,9 @@ class Installer:
self._installer.remove(operation.package) self._installer.remove(operation.package)
def _populate_local_repo(self, local_repo, ops): def _populate_local_repo(
self, local_repo, ops
): # type: (Repository, List[Operation]) -> None
for op in ops: for op in ops:
if isinstance(op, Uninstall): if isinstance(op, Uninstall):
continue continue
...@@ -472,8 +482,8 @@ class Installer: ...@@ -472,8 +482,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 # type: Repository self, locked_repository
): # type: (...) -> List[Operation] ): # type: (Repository) -> List[Operation]
installed_repo = self._installed_repository installed_repo = self._installed_repository
ops = [] ops = []
......
from typing import TYPE_CHECKING
from typing import List
from .base_installer import BaseInstaller from .base_installer import BaseInstaller
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class NoopInstaller(BaseInstaller): class NoopInstaller(BaseInstaller):
def __init__(self): def __init__(self): # type: () -> None
self._installs = [] self._installs = []
self._updates = [] self._updates = []
self._removals = [] self._removals = []
@property @property
def installs(self): def installs(self): # type: () -> List["Package"]
return self._installs return self._installs
@property @property
def updates(self): def updates(self): # type: () -> List["Package"]
return self._updates return self._updates
@property @property
def removals(self): def removals(self): # type: () -> List["Package"]
return self._removals return self._removals
def install(self, package): def install(self, package): # type: ("Package") -> None
self._installs.append(package) self._installs.append(package)
def update(self, source, target): def update(self, source, target): # type: ("Package", "Package") -> None
self._updates.append((source, target)) self._updates.append((source, target))
def remove(self, package): def remove(self, package): # type: ("Package") -> None
self._removals.append(package) self._removals.append(package)
from typing import Union
from .install import Install from .install import Install
from .uninstall import Uninstall from .uninstall import Uninstall
from .update import Update from .update import Update
OperationTypes = Union[Install, Uninstall, Update]
from typing import TYPE_CHECKING
from typing import Optional
from .operation import Operation from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class Install(Operation): class Install(Operation):
def __init__(self, package, reason=None, priority=0): def __init__(
self, package, reason=None, priority=0
): # type: ("Package", Optional[str], int) -> 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): def package(self): # type: () -> "Package"
return self._package return self._package
@property @property
def job_type(self): def job_type(self): # type: () -> str
return "install" return "install"
def __str__(self): def __str__(self): # type: () -> 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): def __repr__(self): # type: () -> 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)
) )
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Union from typing import TYPE_CHECKING
from typing import Optional
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class Operation(object): class Operation(object):
def __init__( def __init__(self, reason=None, priority=0): # type: (Optional[str], int) -> None
self, reason=None, priority=0
): # type: (Union[str, None], int) -> None
self._reason = reason self._reason = reason
self._skipped = False self._skipped = False
...@@ -26,7 +29,7 @@ class Operation(object): ...@@ -26,7 +29,7 @@ class Operation(object):
return self._skipped return self._skipped
@property @property
def skip_reason(self): # type: () -> Union[str, None] def skip_reason(self): # type: () -> Optional[str]
return self._skip_reason return self._skip_reason
@property @property
...@@ -34,10 +37,10 @@ class Operation(object): ...@@ -34,10 +37,10 @@ class Operation(object):
return self._priority return self._priority
@property @property
def package(self): def package(self): # type: () -> "Package"
raise NotImplementedError() raise NotImplementedError()
def format_version(self, package): # type: (...) -> str def format_version(self, package): # type: ("Package") -> str
return package.full_pretty_version return package.full_pretty_version
def skip(self, reason): # type: (str) -> Operation def skip(self, reason): # type: (str) -> Operation
......
from typing import TYPE_CHECKING
from typing import Optional
from .operation import Operation from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class Uninstall(Operation): class Uninstall(Operation):
def __init__(self, package, reason=None, priority=float("inf")): def __init__(
self, package, reason=None, priority=float("inf")
): # type: ("Package", Optional[str], int) -> 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): def package(self): # type: () -> "Package"
return self._package return self._package
@property @property
def job_type(self): def job_type(self): # type: () -> str
return "uninstall" return "uninstall"
def __str__(self): def __str__(self): # type: () -> 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): def __repr__(self): # type: () -> 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)
) )
from typing import TYPE_CHECKING
from typing import Optional
from .operation import Operation from .operation import Operation
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class Update(Operation): class Update(Operation):
def __init__(self, initial, target, reason=None, priority=0): def __init__(
self, initial, target, reason=None, priority=0
): # type: ("Package", "Package", Optional[str], int) -> 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): def initial_package(self): # type: () -> "Package"
return self._initial_package return self._initial_package
@property @property
def target_package(self): def target_package(self): # type: () -> "Package"
return self._target_package return self._target_package
@property @property
def package(self): def package(self): # type: () -> "Package"
return self._target_package return self._target_package
@property @property
def job_type(self): def job_type(self): # type: () -> str
return "update" return "update"
def __str__(self): def __str__(self): # type: () -> 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),
...@@ -32,7 +41,7 @@ class Update(Operation): ...@@ -32,7 +41,7 @@ class Update(Operation):
self.format_version(self.target_package), self.format_version(self.target_package),
) )
def __repr__(self): def __repr__(self): # type: () -> 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),
......
...@@ -3,6 +3,9 @@ import tempfile ...@@ -3,6 +3,9 @@ import tempfile
import urllib.parse import urllib.parse
from subprocess import CalledProcessError from subprocess import CalledProcessError
from typing import TYPE_CHECKING
from typing import Any
from typing import Union
from clikit.api.io import IO from clikit.api.io import IO
...@@ -15,13 +18,17 @@ from poetry.utils.helpers import safe_rmtree ...@@ -15,13 +18,17 @@ from poetry.utils.helpers import safe_rmtree
from .base_installer import BaseInstaller from .base_installer import BaseInstaller
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
class PipInstaller(BaseInstaller): class PipInstaller(BaseInstaller):
def __init__(self, env, io, pool): # type: (Env, IO, Pool) -> None def __init__(self, env, io, pool): # type: (Env, IO, 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): def install(self, package, update=False): # type: ("Package", bool) -> None
if package.source_type == "directory": if package.source_type == "directory":
self.install_directory(package) self.install_directory(package)
...@@ -90,7 +97,7 @@ class PipInstaller(BaseInstaller): ...@@ -90,7 +97,7 @@ class PipInstaller(BaseInstaller):
self.run(*args) self.run(*args)
def update(self, package, target): def update(self, package, target): # type: ("Package", "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
...@@ -98,7 +105,7 @@ class PipInstaller(BaseInstaller): ...@@ -98,7 +105,7 @@ class PipInstaller(BaseInstaller):
self.install(target, update=True) self.install(target, update=True)
def remove(self, package): def remove(self, package): # type: ("Package") -> None
try: try:
self.run("uninstall", package.name, "-y") self.run("uninstall", package.name, "-y")
except CalledProcessError as e: except CalledProcessError as e:
...@@ -120,10 +127,10 @@ class PipInstaller(BaseInstaller): ...@@ -120,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: (...) -> str def run(self, *args, **kwargs): # type: (*Any,**Any) -> str
return self._env.run_pip(*args, **kwargs) return self._env.run_pip(*args, **kwargs)
def requirement(self, package, formatted=False): def requirement(self, package, formatted=False): # type: ("Package", bool) -> 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:
...@@ -164,7 +171,7 @@ class PipInstaller(BaseInstaller): ...@@ -164,7 +171,7 @@ class PipInstaller(BaseInstaller):
return "{}=={}".format(package.name, package.version) return "{}=={}".format(package.name, package.version)
def create_temporary_requirement(self, package): def create_temporary_requirement(self, package): # type: ("Package") -> str
fd, name = tempfile.mkstemp( fd, name = tempfile.mkstemp(
"reqs.txt", "{}-{}".format(package.name, package.version) "reqs.txt", "{}-{}".format(package.name, package.version)
) )
...@@ -176,7 +183,7 @@ class PipInstaller(BaseInstaller): ...@@ -176,7 +183,7 @@ class PipInstaller(BaseInstaller):
return name return name
def install_directory(self, package): def install_directory(self, package): # type: ("Package") -> Union[str, int]
from poetry.factory import Factory from poetry.factory import Factory
from poetry.io.null_io import NullIO from poetry.io.null_io import NullIO
...@@ -233,7 +240,7 @@ class PipInstaller(BaseInstaller): ...@@ -233,7 +240,7 @@ class PipInstaller(BaseInstaller):
return self.run(*args) return self.run(*args)
def install_git(self, package): def install_git(self, package): # type: ("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
......
from typing import Any
from cleo.io.io_mixin import IOMixin from cleo.io.io_mixin import IOMixin
from clikit.io import NullIO as BaseNullIO from clikit.io import NullIO as BaseNullIO
...@@ -7,5 +9,5 @@ class NullIO(IOMixin, BaseNullIO): ...@@ -7,5 +9,5 @@ class NullIO(IOMixin, BaseNullIO):
A wrapper around CliKit's NullIO. A wrapper around CliKit's NullIO.
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs): # type: (*Any, **Any) -> None
super(NullIO, self).__init__(*args, **kwargs) super(NullIO, self).__init__(*args, **kwargs)
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Dict
from typing import Optional from typing import Optional
from tomlkit import dumps from tomlkit import dumps
...@@ -9,7 +10,8 @@ from poetry.utils.helpers import module_name ...@@ -9,7 +10,8 @@ from poetry.utils.helpers import module_name
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.pyproject.toml import PyProjectTOML from poetry.core.pyproject.toml import PyProjectTOML # noqa
from poetry.utils._compat import Path # noqa
TESTS_DEFAULT = u"""from {package_name} import __version__ TESTS_DEFAULT = u"""from {package_name} import __version__
...@@ -45,21 +47,21 @@ license = "" ...@@ -45,21 +47,21 @@ license = ""
""" """
BUILD_SYSTEM_MIN_VERSION = "1.0.0" BUILD_SYSTEM_MIN_VERSION = "1.0.0"
BUILD_SYSTEM_MAX_VERSION = None BUILD_SYSTEM_MAX_VERSION = None # type: Optional[str]
class Layout(object): class Layout(object):
def __init__( def __init__(
self, self,
project, project, # type: str
version="0.1.0", version="0.1.0", # type: str
description="", description="", # type: str
readme_format="md", readme_format="md", # type: str
author=None, author=None, # type: Optional[str]
license=None, license=None, # type: Optional[str]
python="*", python="*", # type: str
dependencies=None, dependencies=None, # type: Optional[Dict[str, str]]
dev_dependencies=None, dev_dependencies=None, # type: Optional[Dict[str, str]]
): ):
self._project = project self._project = project
self._package_name = module_name(project) self._package_name = module_name(project)
...@@ -76,7 +78,7 @@ class Layout(object): ...@@ -76,7 +78,7 @@ class Layout(object):
self._author = author self._author = author
def create(self, path, with_tests=True): def create(self, path, with_tests=True): # type: (Path, bool) -> None
path.mkdir(parents=True, exist_ok=True) path.mkdir(parents=True, exist_ok=True)
self._create_default(path) self._create_default(path)
...@@ -129,10 +131,10 @@ class Layout(object): ...@@ -129,10 +131,10 @@ class Layout(object):
return content return content
def _create_default(self, path, src=True): def _create_default(self, path, src=True): # type: (Path, bool) -> None
raise NotImplementedError() raise NotImplementedError()
def _create_readme(self, path): def _create_readme(self, path): # type: (Path) -> None
if self._readme_format == "rst": if self._readme_format == "rst":
readme_file = path / "README.rst" readme_file = path / "README.rst"
else: else:
...@@ -140,7 +142,7 @@ class Layout(object): ...@@ -140,7 +142,7 @@ class Layout(object):
readme_file.touch() readme_file.touch()
def _create_tests(self, path): def _create_tests(self, path): # type: (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)
...@@ -155,7 +157,7 @@ class Layout(object): ...@@ -155,7 +157,7 @@ class Layout(object):
) )
) )
def _write_poetry(self, path): def _write_poetry(self, path): # type: ("Path") -> None
content = self.generate_poetry_content() content = self.generate_poetry_content()
poetry = path / "pyproject.toml" poetry = path / "pyproject.toml"
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import TYPE_CHECKING
from .layout import Layout from .layout import Layout
if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa
DEFAULT = u"""__version__ = '{version}' DEFAULT = u"""__version__ = '{version}'
""" """
class SrcLayout(Layout): class SrcLayout(Layout):
def _create_default(self, path): def _create_default(self, path): # type: ("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"
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import TYPE_CHECKING
from .layout import Layout from .layout import Layout
if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa
DEFAULT = u"""__version__ = '{version}' DEFAULT = u"""__version__ = '{version}'
""" """
class StandardLayout(Layout): class StandardLayout(Layout):
def _create_default(self, path): def _create_default(self, path): # type: ("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"
......
...@@ -6,6 +6,8 @@ import shutil ...@@ -6,6 +6,8 @@ import shutil
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import List
from poetry.core.masonry.builders.builder import Builder from poetry.core.masonry.builders.builder import Builder
from poetry.core.masonry.builders.sdist import SdistBuilder from poetry.core.masonry.builders.sdist import SdistBuilder
...@@ -16,6 +18,12 @@ from poetry.utils._compat import decode ...@@ -16,6 +18,12 @@ from poetry.utils._compat import decode
from poetry.utils.helpers import is_dir_writable from poetry.utils.helpers import is_dir_writable
if TYPE_CHECKING:
from clikit.api.io import IO # noqa
from poetry.core.poetry import Poetry # noqa
from poetry.utils.env import Env # noqa
SCRIPT_TEMPLATE = """\ SCRIPT_TEMPLATE = """\
#!{python} #!{python}
from {module} import {callable_holder} from {module} import {callable_holder}
...@@ -30,13 +38,13 @@ WINDOWS_CMD_TEMPLATE = """\ ...@@ -30,13 +38,13 @@ WINDOWS_CMD_TEMPLATE = """\
class EditableBuilder(Builder): class EditableBuilder(Builder):
def __init__(self, poetry, env, io): def __init__(self, poetry, env, io): # type: ("Poetry", "Env", "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): def build(self): # type: () -> 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
...@@ -58,11 +66,11 @@ class EditableBuilder(Builder): ...@@ -58,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): def _run_build_script(self, build_script): # type: (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): def _setup_build(self): # type: () -> 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()
...@@ -94,7 +102,7 @@ class EditableBuilder(Builder): ...@@ -94,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): def _add_pth(self): # type: () -> 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 (
...@@ -126,7 +134,7 @@ class EditableBuilder(Builder): ...@@ -126,7 +134,7 @@ class EditableBuilder(Builder):
) )
return [] return []
def _add_scripts(self): def _add_scripts(self): # type: () -> List[Path]
added = [] added = []
entry_points = self.convert_entry_points() entry_points = self.convert_entry_points()
...@@ -185,7 +193,7 @@ class EditableBuilder(Builder): ...@@ -185,7 +193,7 @@ class EditableBuilder(Builder):
return added return added
def _add_dist_info(self, added_files): def _add_dist_info(self, added_files): # type: (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[:]
...@@ -239,7 +247,7 @@ class EditableBuilder(Builder): ...@@ -239,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): def _get_file_hash(self, filepath): # type: (Path) -> str
hashsum = hashlib.sha256() hashsum = hashlib.sha256()
with filepath.open("rb") as src: with filepath.open("rb") as src:
while True: while True:
...@@ -252,6 +260,6 @@ class EditableBuilder(Builder): ...@@ -252,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): def _debug(self, msg): # type: (str) -> None
if self._io.is_debug(): if self._io.is_debug():
self._io.write_line(msg) self._io.write_line(msg)
from typing import TYPE_CHECKING
from typing import Dict
from typing import List
from .version_solver import VersionSolver from .version_solver import VersionSolver
def resolve_version(root, provider, locked=None, use_latest=None): if TYPE_CHECKING:
from poetry.core.packages import DependencyPackage # noqa
from poetry.core.packages import ProjectPackage # noqa
from poetry.puzzle.provider import Provider # noqa
from .result import SolverResult # noqa
def resolve_version(
root, provider, locked=None, use_latest=None
): # type: ("ProjectPackage", "Provider", Dict[str, "DependencyPackage"],List[str]) -> "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()
from typing import TYPE_CHECKING
from typing import Any from typing import Any
from typing import Optional
from .incompatibility import Incompatibility
from .term import Term from .term import Term
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from .incompatibility import Incompatibility # noqa
class Assignment(Term): class Assignment(Term):
""" """
A term in a PartialSolution that tracks some additional metadata. A term in a PartialSolution that tracks some additional metadata.
""" """
def __init__(self, dependency, is_positive, decision_level, index, cause=None): def __init__(
self, dependency, is_positive, decision_level, index, cause=None
): # type: ("Dependency", bool, int, int, Optional["Incompatibility"]) -> 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
...@@ -25,19 +35,19 @@ class Assignment(Term): ...@@ -25,19 +35,19 @@ class Assignment(Term):
return self._index return self._index
@property @property
def cause(self): # type: () -> Incompatibility def cause(self): # type: () -> "Incompatibility"
return self._cause return self._cause
@classmethod @classmethod
def decision( def decision(
cls, package, decision_level, index cls, package, decision_level, index
): # type: (Any, int, int) -> Assignment ): # type: ("Package", int, int) -> 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, dependency, is_positive, cause, decision_level, index
): # type: (Any, bool, Incompatibility, int, int) -> Assignment ): # type: (Any, bool, "Incompatibility", int, 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): # type: () -> bool
......
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional
from typing import Tuple from typing import Tuple
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
...@@ -14,10 +15,10 @@ class SolveFailure(Exception): ...@@ -14,10 +15,10 @@ class SolveFailure(Exception):
self._incompatibility = incompatibility self._incompatibility = incompatibility
@property @property
def message(self): def message(self): # type: () -> str
return str(self) return str(self)
def __str__(self): def __str__(self): # type: () -> str
return _Writer(self._incompatibility).write() return _Writer(self._incompatibility).write()
...@@ -25,12 +26,12 @@ class _Writer: ...@@ -25,12 +26,12 @@ class _Writer:
def __init__(self, root): # type: (Incompatibility) -> None def __init__(self, root): # type: (Incompatibility) -> None
self._root = root self._root = root
self._derivations = {} # type: Dict[Incompatibility, int] self._derivations = {} # type: Dict[Incompatibility, int]
self._lines = [] # type: List[Tuple[str, int]] self._lines = [] # type: List[Tuple[str, Optional[int]]]
self._line_numbers = {} # type: Dict[Incompatibility, int] self._line_numbers = {} # type: Dict[Incompatibility, int]
self._count_derivations(self._root) self._count_derivations(self._root)
def write(self): def write(self): # type: () -> str
buffer = [] buffer = []
required_python_version_notification = False required_python_version_notification = False
...@@ -113,7 +114,7 @@ class _Writer: ...@@ -113,7 +114,7 @@ class _Writer:
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)
cause = incompatibility.cause # type: ConflictCause cause = incompatibility.cause
details_for_cause = {} details_for_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
......
from typing import Dict from typing import Dict
from typing import Generator from typing import Generator
from typing import List from typing import List
from typing import Optional
from typing import Union
from .incompatibility_cause import ConflictCause from .incompatibility_cause import ConflictCause
from .incompatibility_cause import DependencyCause from .incompatibility_cause import DependencyCause
...@@ -82,11 +84,15 @@ class Incompatibility: ...@@ -82,11 +84,15 @@ class Incompatibility:
return self._terms return self._terms
@property @property
def cause(self): # type: () -> IncompatibilityCause def cause(
self,
): # type: () -> Union[RootCause, NoVersionsCause, DependencyCause, ConflictCause, PythonCause, PlatformCause, PackageNotFoundCause]
return self._cause return self._cause
@property @property
def external_incompatibilities(self): # type: () -> Generator[Incompatibility] def external_incompatibilities(
self,
): # type: () -> Generator[Union[ConflictCause, Incompatibility]]
""" """
Returns all external incompatibilities in this incompatibility's Returns all external incompatibilities in this incompatibility's
derivation graph. derivation graph.
...@@ -106,7 +112,7 @@ class Incompatibility: ...@@ -106,7 +112,7 @@ class Incompatibility:
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): def __str__(self): # type: () -> str
if isinstance(self._cause, DependencyCause): if isinstance(self._cause, DependencyCause):
assert len(self._terms) == 2 assert len(self._terms) == 2
...@@ -222,7 +228,7 @@ class Incompatibility: ...@@ -222,7 +228,7 @@ class Incompatibility:
def and_to_string( def and_to_string(
self, other, details, this_line, other_line self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> str ): # type: (Incompatibility, dict, Optional[int], 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
...@@ -241,18 +247,18 @@ class Incompatibility: ...@@ -241,18 +247,18 @@ class Incompatibility:
buffer = [str(self)] buffer = [str(self)]
if this_line is not None: if this_line is not None:
buffer.append(" " + this_line) buffer.append(" " + str(this_line))
buffer.append(" and {}".format(str(other))) buffer.append(" and {}".format(str(other)))
if other_line is not None: if other_line is not None:
buffer.append(" " + other_line) buffer.append(" " + str(other_line))
return "\n".join(buffer) return "\n".join(buffer)
def _try_requires_both( def _try_requires_both(
self, other, details, this_line, other_line self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> str ): # type: (Incompatibility, dict, Optional[int], 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
...@@ -298,7 +304,7 @@ class Incompatibility: ...@@ -298,7 +304,7 @@ class Incompatibility:
def _try_requires_through( def _try_requires_through(
self, other, details, this_line, other_line self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> str ): # type: (Incompatibility, dict, int, 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
...@@ -376,7 +382,7 @@ class Incompatibility: ...@@ -376,7 +382,7 @@ class Incompatibility:
def _try_requires_forbidden( def _try_requires_forbidden(
self, other, details, this_line, other_line self, other, details, this_line, other_line
): # type: (Incompatibility, dict, int, int) -> str ): # type: (Incompatibility, dict, int, int) -> 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
...@@ -430,13 +436,13 @@ class Incompatibility: ...@@ -430,13 +436,13 @@ class Incompatibility:
return "".join(buffer) return "".join(buffer)
def _terse(self, term, allow_every=False): def _terse(self, term, allow_every=False): # type: (Term, bool) -> 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) -> Term def _single_term_where(self, callable): # type: (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):
...@@ -449,5 +455,5 @@ class Incompatibility: ...@@ -449,5 +455,5 @@ class Incompatibility:
return found return found
def __repr__(self): def __repr__(self): # type: () -> str
return "<Incompatibility {}>".format(str(self)) return "<Incompatibility {}>".format(str(self))
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from poetry.mixology.incompatibility import Incompatibility # noqa
class IncompatibilityCause(Exception): class IncompatibilityCause(Exception):
""" """
The reason and Incompatibility's terms are incompatible. The reason and Incompatibility's terms are incompatible.
...@@ -25,19 +32,21 @@ class ConflictCause(IncompatibilityCause): ...@@ -25,19 +32,21 @@ class ConflictCause(IncompatibilityCause):
during conflict resolution. during conflict resolution.
""" """
def __init__(self, conflict, other): def __init__(
self, conflict, other
): # type: ("Incompatibility", "Incompatibility") -> None
self._conflict = conflict self._conflict = conflict
self._other = other self._other = other
@property @property
def conflict(self): def conflict(self): # type: () -> "Incompatibility"
return self._conflict return self._conflict
@property @property
def other(self): def other(self): # type: () -> "Incompatibility"
return self._other return self._other
def __str__(self): def __str__(self): # type: () -> str
return str(self._conflict) return str(self._conflict)
...@@ -48,16 +57,16 @@ class PythonCause(IncompatibilityCause): ...@@ -48,16 +57,16 @@ class PythonCause(IncompatibilityCause):
with the current python version. with the current python version.
""" """
def __init__(self, python_version, root_python_version): def __init__(self, python_version, root_python_version): # type: (str, 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): def python_version(self): # type: () -> str
return self._python_version return self._python_version
@property @property
def root_python_version(self): def root_python_version(self): # type: () -> str
return self._root_python_version return self._root_python_version
...@@ -67,11 +76,11 @@ class PlatformCause(IncompatibilityCause): ...@@ -67,11 +76,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): def __init__(self, platform): # type: (str) -> None
self._platform = platform self._platform = platform
@property @property
def platform(self): def platform(self): # type: () -> str
return self._platform return self._platform
...@@ -81,9 +90,9 @@ class PackageNotFoundCause(IncompatibilityCause): ...@@ -81,9 +90,9 @@ class PackageNotFoundCause(IncompatibilityCause):
source. source.
""" """
def __init__(self, error): def __init__(self, error): # type: (Exception) -> None
self._error = error self._error = error
@property @property
def error(self): def error(self): # type: () -> Exception
return self._error return self._error
from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import List from typing import List
from poetry.core.packages import Dependency
from poetry.core.packages import Package
from .assignment import Assignment from .assignment import Assignment
from .incompatibility import Incompatibility from .incompatibility import Incompatibility
from .set_relation import SetRelation from .set_relation import SetRelation
from .term import Term from .term import Term
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
from poetry.packages import DependencyPackage # noqa
class PartialSolution: class PartialSolution:
""" """
# A list of Assignments that represent the solver's current best guess about # A list of Assignments that represent the solver's current best guess about
...@@ -19,13 +23,13 @@ class PartialSolution: ...@@ -19,13 +23,13 @@ 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): def __init__(self): # type: () -> 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 = [] # type: List[Assignment]
# The decisions made for each package. # The decisions made for each package.
self._decisions = dict() # type: Dict[str, Package] self._decisions = dict() # type: Dict[str, "Package"]
# 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.
...@@ -48,7 +52,7 @@ class PartialSolution: ...@@ -48,7 +52,7 @@ class PartialSolution:
self._backtracking = False self._backtracking = False
@property @property
def decisions(self): # type: () -> List[Package] def decisions(self): # type: () -> List["Package"]
return list(self._decisions.values()) return list(self._decisions.values())
@property @property
...@@ -60,14 +64,14 @@ class PartialSolution: ...@@ -60,14 +64,14 @@ class PartialSolution:
return self._attempted_solutions return self._attempted_solutions
@property @property
def unsatisfied(self): # type: () -> List[Dependency] def unsatisfied(self): # type: () -> 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): # type: ("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.
...@@ -88,7 +92,7 @@ class PartialSolution: ...@@ -88,7 +92,7 @@ class PartialSolution:
def derive( def derive(
self, dependency, is_positive, cause self, dependency, is_positive, cause
): # type: (Dependency, bool, Incompatibility) -> None ): # type: ("Dependency", bool, Incompatibility) -> None
""" """
Adds an assignment of package as a derivation. Adds an assignment of package as a derivation.
""" """
...@@ -170,7 +174,7 @@ class PartialSolution: ...@@ -170,7 +174,7 @@ class PartialSolution:
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.
""" """
assigned_term = None # type: Term assigned_term = None
for assignment in self._assignments: for assignment in self._assignments:
if assignment.dependency.complete_name != term.dependency.complete_name: if assignment.dependency.complete_name != term.dependency.complete_name:
......
from typing import TYPE_CHECKING
from typing import List
if TYPE_CHECKING:
from poetry.core.packages import Package # noqa
from poetry.core.packages import ProjectPackage # noqa
class SolverResult: class SolverResult:
def __init__(self, root, packages, attempted_solutions): def __init__(
self, root, packages, attempted_solutions
): # type: ("ProjectPackage", List["Package"], 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): def packages(self): # type: () -> List["Package"]
return self._packages return self._packages
@property @property
def attempted_solutions(self): def attempted_solutions(self): # type: () -> int
return self._attempted_solutions return self._attempted_solutions
from typing import TYPE_CHECKING
from typing import List
from crashtest.contracts.solution import Solution from crashtest.contracts.solution import Solution
if TYPE_CHECKING:
from poetry.mixology.incompatibility_cause import PackageNotFoundCause # noqa
class PythonRequirementSolution(Solution): class PythonRequirementSolution(Solution):
def __init__(self, exception): def __init__(self, exception): # type: ("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
...@@ -37,15 +44,15 @@ class PythonRequirementSolution(Solution): ...@@ -37,15 +44,15 @@ class PythonRequirementSolution(Solution):
self._description = description self._description = description
@property @property
def solution_title(self) -> str: def solution_title(self): # type: () -> str
return self._title return self._title
@property @property
def solution_description(self): def solution_description(self): # type: () -> str
return self._description return self._description
@property @property
def documentation_links(self): def documentation_links(self): # type: () -> 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",
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Union from typing import TYPE_CHECKING
from typing import Optional
from poetry.core.packages import Dependency from poetry.core.packages import Dependency
from .set_relation import SetRelation from .set_relation import SetRelation
if TYPE_CHECKING:
from poetry.core.semver import VersionTypes # noqa
class Term(object): class Term(object):
""" """
A statement about a package which is true or false for a given selection of A statement about a package which is true or false for a given selection of
...@@ -23,11 +28,11 @@ class Term(object): ...@@ -23,11 +28,11 @@ class Term(object):
return Term(self._dependency, not self.is_positive()) return Term(self._dependency, not self.is_positive())
@property @property
def dependency(self): def dependency(self): # type: () -> Dependency
return self._dependency return self._dependency
@property @property
def constraint(self): def constraint(self): # type: () -> "VersionTypes"
return self._dependency.constraint return self._dependency.constraint
def is_positive(self): # type: () -> bool def is_positive(self): # type: () -> bool
...@@ -106,7 +111,7 @@ class Term(object): ...@@ -106,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) -> Union[Term, None] def intersect(self, other): # type: (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
...@@ -147,21 +152,23 @@ class Term(object): ...@@ -147,21 +152,23 @@ class Term(object):
""" """
return self.intersect(other.inverse) return self.intersect(other.inverse)
def _compatible_dependency(self, other): def _compatible_dependency(self, other): # type: (Term) -> bool
return ( return (
self.dependency.is_root self.dependency.is_root
or other.is_root or other.is_root
or other.is_same_package_as(self.dependency) or other.is_same_package_as(self.dependency)
) )
def _non_empty_term(self, constraint, is_positive): def _non_empty_term(
self, constraint, is_positive
): # type: ("VersionTypes", bool) -> 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): def __str__(self): # type: () -> 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): def __repr__(self): # type: () -> str
return "<Term {}>".format(str(self)) return "<Term {}>".format(str(self))
...@@ -4,7 +4,7 @@ import time ...@@ -4,7 +4,7 @@ import time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Union from typing import Optional
from poetry.core.packages import Dependency from poetry.core.packages import Dependency
from poetry.core.packages import Package from poetry.core.packages import Package
...@@ -130,7 +130,7 @@ class VersionSolver: ...@@ -130,7 +130,7 @@ class VersionSolver:
def _propagate_incompatibility( def _propagate_incompatibility(
self, incompatibility self, incompatibility
): # type: (Incompatibility) -> Union[str, _conflict, None] ): # type: (Incompatibility) -> Optional[str, _conflict]
""" """
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.
...@@ -317,7 +317,7 @@ class VersionSolver: ...@@ -317,7 +317,7 @@ class VersionSolver:
raise SolveFailure(incompatibility) raise SolveFailure(incompatibility)
def _choose_package_version(self): # type: () -> Union[str, None] def _choose_package_version(self): # type: () -> Optional[str]
""" """
Tries to select a version of a required package. Tries to select a version of a required package.
...@@ -331,7 +331,7 @@ class VersionSolver: ...@@ -331,7 +331,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): def _get_min(dependency): # type: (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.
...@@ -447,7 +447,7 @@ class VersionSolver: ...@@ -447,7 +447,7 @@ class VersionSolver:
incompatibility incompatibility
) )
def _get_locked(self, dependency): # type: (Dependency) -> Union[Package, None] def _get_locked(self, dependency): # type: (Dependency) -> Optional[Package]
if dependency.name in self._use_latest: if dependency.name in self._use_latest:
return return
...@@ -460,5 +460,5 @@ class VersionSolver: ...@@ -460,5 +460,5 @@ class VersionSolver:
return locked return locked
def _log(self, text): def _log(self, text): # type: (str) -> None
self._provider.debug(text, self._solution.attempted_solutions) self._provider.debug(text, self._solution.attempted_solutions)
from typing import Any
from typing import List from typing import List
from typing import Union
from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
...@@ -17,7 +19,7 @@ class DependencyPackage(object): ...@@ -17,7 +19,7 @@ class DependencyPackage(object):
def package(self): # type: () -> Package def package(self): # type: () -> Package
return self._package return self._package
def clone(self): # type: () -> DependencyPackage def clone(self): # type: () -> "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): # type: (List[str]) -> "DependencyPackage"
...@@ -26,25 +28,25 @@ class DependencyPackage(object): ...@@ -26,25 +28,25 @@ class DependencyPackage(object):
def without_features(self): # type: () -> "DependencyPackage" def without_features(self): # type: () -> "DependencyPackage"
return self.with_features([]) return self.with_features([])
def __getattr__(self, name): def __getattr__(self, name): # type: (str) -> Any
return getattr(self._package, name) return getattr(self._package, name)
def __setattr__(self, key, value): def __setattr__(self, key, value): # type: (str, 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): def __str__(self): # type: () -> str
return str(self._package) return str(self._package)
def __repr__(self): def __repr__(self): # type: () -> str
return repr(self._package) return repr(self._package)
def __hash__(self): def __hash__(self): # type: () -> int
return hash(self._package) return hash(self._package)
def __eq__(self, other): def __eq__(self, other): # type: (Union[Package, "DependencyPackage"]) -> bool
if isinstance(other, DependencyPackage): if isinstance(other, DependencyPackage):
other = other.package other = other.package
......
...@@ -6,6 +6,7 @@ import re ...@@ -6,6 +6,7 @@ import re
from copy import deepcopy from copy import deepcopy
from hashlib import sha256 from hashlib import sha256
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import Dict from typing import Dict
from typing import Iterable from typing import Iterable
from typing import Iterator from typing import Iterator
...@@ -26,7 +27,7 @@ from tomlkit.exceptions import TOMLKitError ...@@ -26,7 +27,7 @@ from tomlkit.exceptions import TOMLKitError
import poetry.repositories import poetry.repositories
from poetry.core.packages import dependency_from_pep_508 from poetry.core.packages import dependency_from_pep_508
from poetry.core.packages.package import Dependency from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
from poetry.core.semver.version import Version from poetry.core.semver.version import Version
...@@ -37,6 +38,9 @@ from poetry.packages import DependencyPackage ...@@ -37,6 +38,9 @@ from poetry.packages import DependencyPackage
from poetry.utils.extras import get_extra_package_names from poetry.utils.extras import get_extra_package_names
if TYPE_CHECKING:
from ptomlkit.toml_document import TOMLDocument # noqa
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -46,7 +50,7 @@ class Locker(object): ...@@ -46,7 +50,7 @@ class Locker(object):
_relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"] _relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"]
def __init__(self, lock, local_config): # type: (Path, dict) -> None def __init__(self, lock, local_config): # type: (Union[str, Path], 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
...@@ -57,7 +61,7 @@ class Locker(object): ...@@ -57,7 +61,7 @@ class Locker(object):
return self._lock return self._lock
@property @property
def lock_data(self): def lock_data(self): # type: () -> 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()
...@@ -382,7 +386,7 @@ class Locker(object): ...@@ -382,7 +386,7 @@ class Locker(object):
yield DependencyPackage(dependency=dependency, package=package) yield DependencyPackage(dependency=dependency, package=package)
def set_lock_data(self, root, packages): # type: (...) -> bool def set_lock_data(self, root, packages): # type: (Package, List[Package]) -> bool
files = table() files = table()
packages = self._lock_packages(packages) packages = self._lock_packages(packages)
# Retrieving hashes # Retrieving hashes
...@@ -427,7 +431,7 @@ class Locker(object): ...@@ -427,7 +431,7 @@ class Locker(object):
return False return False
def _write_lock_data(self, data): def _write_lock_data(self, data): # type: ("TOMLDocument") -> None
self.lock.write(data) self.lock.write(data)
# Checking lock file data consistency # Checking lock file data consistency
...@@ -452,7 +456,7 @@ class Locker(object): ...@@ -452,7 +456,7 @@ class Locker(object):
return content_hash return content_hash
def _get_lock_data(self): # type: () -> dict def _get_lock_data(self): # type: () -> "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")
...@@ -484,9 +488,7 @@ class Locker(object): ...@@ -484,9 +488,7 @@ class Locker(object):
return lock_data return lock_data
def _lock_packages( def _lock_packages(self, packages): # type: (List[Package]) -> list
self, packages
): # type: (List['poetry.packages.Package']) -> list
locked = [] locked = []
for package in sorted(packages, key=lambda x: x.name): for package in sorted(packages, key=lambda x: x.name):
......
from typing import TYPE_CHECKING
from typing import List
from typing import Union
from .dependency_package import DependencyPackage from .dependency_package import DependencyPackage
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
class PackageCollection(list): class PackageCollection(list):
def __init__(self, dependency, packages=None): def __init__(
self, dependency, packages=None
): # type: (Dependency, List[Union["Package", DependencyPackage]]) -> None
self._dependency = dependency self._dependency = dependency
if packages is None: if packages is None:
...@@ -13,7 +24,7 @@ class PackageCollection(list): ...@@ -13,7 +24,7 @@ class PackageCollection(list):
for package in packages: for package in packages:
self.append(package) self.append(package)
def append(self, package): def append(self, package): # type: (Union["Package", DependencyPackage]) -> None
if isinstance(package, DependencyPackage): if isinstance(package, DependencyPackage):
package = package.package package = package.package
......
import logging import logging
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import List
from typing import Optional from typing import Optional
from typing import Union
from poetry.utils.helpers import get_cert from poetry.utils.helpers import get_cert
from poetry.utils.helpers import get_client_cert from poetry.utils.helpers import get_client_cert
...@@ -10,6 +13,13 @@ from poetry.utils.password_manager import PasswordManager ...@@ -10,6 +13,13 @@ from poetry.utils.password_manager import PasswordManager
from .uploader import Uploader from .uploader import Uploader
if TYPE_CHECKING:
from cleo.io import BufferedIO # noqa
from cleo.io import ConsoleIO # noqa
from clikit.io import NullIO # noqa
from ..poetry import Poetry # noqa
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -18,7 +28,9 @@ class Publisher: ...@@ -18,7 +28,9 @@ class Publisher:
Registers and publishes packages to remote repositories. Registers and publishes packages to remote repositories.
""" """
def __init__(self, poetry, io): def __init__(
self, poetry, io
): # type: ("Poetry", Union["ConsoleIO", "BufferedIO", "NullIO"]) -> None
self._poetry = poetry self._poetry = poetry
self._package = poetry.package self._package = poetry.package
self._io = io self._io = io
...@@ -26,7 +38,7 @@ class Publisher: ...@@ -26,7 +38,7 @@ class Publisher:
self._password_manager = PasswordManager(poetry.config) self._password_manager = PasswordManager(poetry.config)
@property @property
def files(self): def files(self): # type: () -> List[Path]
return self._uploader.files return self._uploader.files
def publish( def publish(
......
...@@ -2,10 +2,12 @@ import hashlib ...@@ -2,10 +2,12 @@ import hashlib
import io import io
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any from typing import Any
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 Tuple
from typing import Union from typing import Union
import requests import requests
...@@ -26,11 +28,17 @@ from poetry.utils.helpers import normalize_version ...@@ -26,11 +28,17 @@ from poetry.utils.helpers import normalize_version
from poetry.utils.patterns import wheel_file_re from poetry.utils.patterns import wheel_file_re
if TYPE_CHECKING:
from cleo.io import ConsoleIO # noqa
from clikit.io import NullIO # noqa
from poetry.poetry import Poetry # noqa
_has_blake2 = hasattr(hashlib, "blake2b") _has_blake2 = hasattr(hashlib, "blake2b")
class UploadError(Exception): class UploadError(Exception):
def __init__(self, error): # type: (Union[ConnectionError, HTTPError]) -> None def __init__(self, error): # type: (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
...@@ -46,7 +54,9 @@ class UploadError(Exception): ...@@ -46,7 +54,9 @@ class UploadError(Exception):
class Uploader: class Uploader:
def __init__(self, poetry, io): def __init__(
self, poetry, io
): # type: ("Poetry", Union["ConsoleIO", "NullIO"]) -> None
self._poetry = poetry self._poetry = poetry
self._package = poetry.package self._package = poetry.package
self._io = io self._io = io
...@@ -54,11 +64,11 @@ class Uploader: ...@@ -54,11 +64,11 @@ class Uploader:
self._password = None self._password = None
@property @property
def user_agent(self): def user_agent(self): # type: () -> str
return user_agent("poetry", __version__) return user_agent("poetry", __version__)
@property @property
def adapter(self): def adapter(self): # type: () -> adapters.HTTPAdapter
retry = util.Retry( retry = util.Retry(
connect=5, connect=5,
total=10, total=10,
...@@ -86,7 +96,7 @@ class Uploader: ...@@ -86,7 +96,7 @@ class Uploader:
return sorted(wheels + tars) return sorted(wheels + tars)
def auth(self, username, password): def auth(self, username, password): # type: (str, str) -> None
self._username = username self._username = username
self._password = password self._password = password
...@@ -101,7 +111,7 @@ class Uploader: ...@@ -101,7 +111,7 @@ class Uploader:
return session return session
def is_authenticated(self): def is_authenticated(self): # type: () -> 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(
...@@ -326,7 +336,7 @@ class Uploader: ...@@ -326,7 +336,7 @@ class Uploader:
return resp return resp
def _prepare_data(self, data): def _prepare_data(self, data): # type: (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)):
...@@ -337,7 +347,7 @@ class Uploader: ...@@ -337,7 +347,7 @@ class Uploader:
return data_to_send return data_to_send
def _get_type(self, file): def _get_type(self, file): # type: (Path) -> str
exts = file.suffixes exts = file.suffixes
if exts[-1] == ".whl": if exts[-1] == ".whl":
return "bdist_wheel" return "bdist_wheel"
......
from typing import Dict
from typing import Tuple
class SolverProblemError(Exception): class SolverProblemError(Exception):
def __init__(self, error): def __init__(self, error): # type: (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): def error(self): # type: () -> Exception
return self._error return self._error
class OverrideNeeded(Exception): class OverrideNeeded(Exception):
def __init__(self, *overrides): def __init__(self, *overrides): # type: (*Dict) -> None
self._overrides = overrides self._overrides = overrides
@property @property
def overrides(self): def overrides(self): # type: () -> Tuple[Dict]
return self._overrides return self._overrides
...@@ -7,8 +7,11 @@ from contextlib import contextmanager ...@@ -7,8 +7,11 @@ from contextlib import contextmanager
from pathlib import Path from pathlib import Path
from tempfile import mkdtemp from tempfile import mkdtemp
from typing import Any from typing import Any
from typing import Dict
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 clikit.ui.components import ProgressIndicator from clikit.ui.components import ProgressIndicator
...@@ -68,10 +71,10 @@ class Provider: ...@@ -68,10 +71,10 @@ class Provider:
def pool(self): # type: () -> Pool def pool(self): # type: () -> Pool
return self._pool return self._pool
def is_debugging(self): def is_debugging(self): # type: () -> bool
return self._is_debugging return self._is_debugging
def set_overrides(self, overrides): def set_overrides(self, overrides): # type: (Dict) -> None
self._overrides = overrides self._overrides = overrides
def load_deferred(self, load_deferred): # type: (bool) -> None def load_deferred(self, load_deferred): # type: (bool) -> None
...@@ -90,7 +93,9 @@ class Provider: ...@@ -90,7 +93,9 @@ class Provider:
self._env = original_env self._env = original_env
self._python_constraint = original_python_constraint self._python_constraint = original_python_constraint
def search_for(self, dependency): # type: (Dependency) -> List[Package] def search_for(
self, dependency
): # type: (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.
...@@ -175,7 +180,7 @@ class Provider: ...@@ -175,7 +180,7 @@ 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, vcs, url, branch=None, tag=None, rev=None, name=None
): # type: (str, str, Optional[str], Optional[str]) -> Package ): # type: (str, str, Optional[str], Optional[str], Optional[str], Optional[str]) -> Package
if vcs != "git": if vcs != "git":
raise ValueError("Unsupported VCS dependency {}".format(vcs)) raise ValueError("Unsupported VCS dependency {}".format(vcs))
...@@ -684,7 +689,7 @@ class Provider: ...@@ -684,7 +689,7 @@ class Provider:
return package return package
def debug(self, message, depth=0): def debug(self, message, depth=0): # type: (str, int) -> 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
...@@ -771,7 +776,7 @@ class Provider: ...@@ -771,7 +776,7 @@ class Provider:
self._io.write(debug_info) self._io.write(debug_info)
@contextmanager @contextmanager
def progress(self): def progress(self): # type: () -> Iterator[None]
if not self._io.output.supports_ansi() or self.is_debugging(): if not self._io.output.supports_ansi() or self.is_debugging():
self._io.write_line("Resolving dependencies...") self._io.write_line("Resolving dependencies...")
yield yield
......
...@@ -3,17 +3,21 @@ import time ...@@ -3,17 +3,21 @@ import time
from collections import defaultdict from collections import defaultdict
from contextlib import contextmanager from contextlib import contextmanager
from typing import TYPE_CHECKING
from typing import Callable
from typing import Dict
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Tuple
from typing import Union
from clikit.io import ConsoleIO from clikit.api.io import IO
from poetry.core.packages import Package from poetry.core.packages import Package
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
from poetry.installation.operations import Install from poetry.installation.operations import Install
from poetry.installation.operations import Uninstall from poetry.installation.operations import Uninstall
from poetry.installation.operations import Update from poetry.installation.operations import Update
from poetry.installation.operations.operation import Operation
from poetry.mixology import resolve_version from poetry.mixology import resolve_version
from poetry.mixology.failure import SolveFailure from poetry.mixology.failure import SolveFailure
from poetry.packages import DependencyPackage from poetry.packages import DependencyPackage
...@@ -26,6 +30,15 @@ from .exceptions import SolverProblemError ...@@ -26,6 +30,15 @@ from .exceptions import SolverProblemError
from .provider import Provider from .provider import Provider
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import DirectoryDependency # noqa
from poetry.core.packages import FileDependency # noqa
from poetry.core.packages import URLDependency # noqa
from poetry.core.packages import VCSDependency # noqa
from poetry.installation.operations import OperationTypes # noqa
class Solver: class Solver:
def __init__( def __init__(
self, self,
...@@ -33,7 +46,7 @@ class Solver: ...@@ -33,7 +46,7 @@ class Solver:
pool, # type: Pool pool, # type: Pool
installed, # type: Repository installed, # type: Repository
locked, # type: Repository locked, # type: Repository
io, # type: ConsoleIO io, # type: IO
remove_untracked=False, # type: bool remove_untracked=False, # type: bool
provider=None, # type: Optional[Provider] provider=None, # type: Optional[Provider]
): ):
...@@ -59,7 +72,7 @@ class Solver: ...@@ -59,7 +72,7 @@ class Solver:
with self.provider.use_environment(env): with self.provider.use_environment(env):
yield yield
def solve(self, use_latest=None): # type: (...) -> List[Operation] def solve(self, use_latest=None): # type: (List[str]) -> 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)
...@@ -191,7 +204,9 @@ class Solver: ...@@ -191,7 +204,9 @@ class Solver:
operations, key=lambda o: (-o.priority, o.package.name, o.package.version,), operations, key=lambda o: (-o.priority, o.package.name, o.package.version,),
) )
def solve_in_compatibility_mode(self, overrides, use_latest=None): def solve_in_compatibility_mode(
self, overrides, use_latest=None
): # type: (Tuple[Dict], List[str]) -> 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)
...@@ -221,7 +236,9 @@ class Solver: ...@@ -221,7 +236,9 @@ class Solver:
return packages, depths return packages, depths
def _solve(self, use_latest=None): def _solve(
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)
...@@ -274,18 +291,20 @@ class Solver: ...@@ -274,18 +291,20 @@ class Solver:
class DFSNode(object): class DFSNode(object):
def __init__(self, id, name, base_name): def __init__(
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): def reachable(self): # type: () -> List
return [] return []
def visit(self, parents): def visit(self, parents): # type: (List[PackageNode]) -> None
pass pass
def __str__(self): def __str__(self): # type: () -> str
return str(self.id) return str(self.id)
...@@ -295,7 +314,9 @@ class VisitedState(enum.Enum): ...@@ -295,7 +314,9 @@ class VisitedState(enum.Enum):
Visited = 2 Visited = 2
def depth_first_search(source, aggregator): def depth_first_search(
source, aggregator
): # type: (PackageNode, Callable) -> List[Tuple[Package, int]]
back_edges = defaultdict(list) back_edges = defaultdict(list)
visited = {} visited = {}
topo_sorted_nodes = [] topo_sorted_nodes = []
...@@ -322,7 +343,9 @@ def depth_first_search(source, aggregator): ...@@ -322,7 +343,9 @@ def depth_first_search(source, aggregator):
return results return results
def dfs_visit(node, back_edges, visited, sorted_nodes): def dfs_visit(
node, back_edges, visited, sorted_nodes
): # type: (PackageNode, Dict[str, List[PackageNode]], Dict[str, VisitedState], 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:
...@@ -343,8 +366,13 @@ def dfs_visit(node, back_edges, visited, sorted_nodes): ...@@ -343,8 +366,13 @@ def dfs_visit(node, back_edges, visited, sorted_nodes):
class PackageNode(DFSNode): class PackageNode(DFSNode):
def __init__( def __init__(
self, package, packages, previous=None, previous_dep=None, dep=None, self,
): package, # type: Package
packages, # type: List[Package]
previous=None, # type: Optional[PackageNode]
previous_dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]]
dep=None, # type: Optional[Union["DirectoryDependency", "FileDependency", "URLDependency", "VCSDependency", "Dependency"]]
): # type: (...) -> None
self.package = package self.package = package
self.packages = packages self.packages = packages
...@@ -366,7 +394,7 @@ class PackageNode(DFSNode): ...@@ -366,7 +394,7 @@ class PackageNode(DFSNode):
package.name, package.name,
) )
def reachable(self): def reachable(self): # type: () -> List[PackageNode]
children = [] # type: List[PackageNode] children = [] # type: List[PackageNode]
if ( if (
...@@ -413,7 +441,7 @@ class PackageNode(DFSNode): ...@@ -413,7 +441,7 @@ class PackageNode(DFSNode):
return children return children
def visit(self, parents): def visit(self, parents): # type: (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(
...@@ -425,7 +453,9 @@ class PackageNode(DFSNode): ...@@ -425,7 +453,9 @@ class PackageNode(DFSNode):
) )
def aggregate_package_nodes(nodes, children): def aggregate_package_nodes(
nodes, children
): # type: (List[PackageNode], List[PackageNode]) -> 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 = (
......
from typing import TYPE_CHECKING
from typing import List
from typing import Optional
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
class BaseRepository(object): class BaseRepository(object):
def __init__(self): def __init__(self): # type: () -> None
self._packages = [] self._packages = []
@property @property
def packages(self): def packages(self): # type: () -> List["Package"]
return self._packages return self._packages
def has_package(self, package): def has_package(self, package): # type: ("Package") -> None
raise NotImplementedError() raise NotImplementedError()
def package(self, name, version, extras=None): def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> None
raise NotImplementedError() raise NotImplementedError()
def find_packages(self, dependency): def find_packages(self, dependency): # type: ("Dependency") -> None
raise NotImplementedError() raise NotImplementedError()
def search(self, query): def search(self, query): # type: (str) -> None
raise NotImplementedError() raise NotImplementedError()
...@@ -5,9 +5,12 @@ import warnings ...@@ -5,9 +5,12 @@ import warnings
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Dict
from typing import Generator from typing import Generator
from typing import List
from typing import Optional from typing import Optional
from typing import Union
import requests import requests
import requests.auth import requests.auth
...@@ -34,6 +37,9 @@ from .exceptions import RepositoryError ...@@ -34,6 +37,9 @@ from .exceptions import RepositoryError
from .pypi_repository import PyPiRepository from .pypi_repository import PyPiRepository
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
try: try:
from html import unescape from html import unescape
except ImportError: except ImportError:
...@@ -69,7 +75,9 @@ class Page: ...@@ -69,7 +75,9 @@ class Page:
".tar", ".tar",
] ]
def __init__(self, url, content, headers): def __init__(
self, url, content, headers
): # type: (str, str, Dict[str, Any]) -> None
if not url.endswith("/"): if not url.endswith("/"):
url += "/" url += "/"
...@@ -127,7 +135,7 @@ class Page: ...@@ -127,7 +135,7 @@ class Page:
if self.link_version(link) == version: if self.link_version(link) == version:
yield link yield link
def link_version(self, link): # type: (Link) -> Union[Version, None] def link_version(self, link): # type: (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")
...@@ -148,7 +156,7 @@ class Page: ...@@ -148,7 +156,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): def clean_link(self, url): # type: (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)."""
...@@ -225,7 +233,7 @@ class LegacyRepository(PyPiRepository): ...@@ -225,7 +233,7 @@ class LegacyRepository(PyPiRepository):
path=parsed.path, path=parsed.path,
) )
def find_packages(self, dependency): def find_packages(self, dependency): # type: ("Dependency") -> List[Package]
packages = [] packages = []
constraint = dependency.constraint constraint = dependency.constraint
...@@ -296,7 +304,9 @@ class LegacyRepository(PyPiRepository): ...@@ -296,7 +304,9 @@ class LegacyRepository(PyPiRepository):
return packages return packages
def package(self, name, version, extras=None): # type: (...) -> Package def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> Package
""" """
Retrieve the release information. Retrieve the release information.
...@@ -320,7 +330,7 @@ class LegacyRepository(PyPiRepository): ...@@ -320,7 +330,7 @@ class LegacyRepository(PyPiRepository):
return package return package
def find_links_for_package(self, package): def find_links_for_package(self, package): # type: (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 []
...@@ -375,7 +385,7 @@ class LegacyRepository(PyPiRepository): ...@@ -375,7 +385,7 @@ class LegacyRepository(PyPiRepository):
return data.asdict() return data.asdict()
def _get(self, endpoint): # type: (str) -> Union[Page, None] def _get(self, endpoint): # type: (str) -> Optional[Page]
url = self._url + endpoint url = self._url + endpoint
try: try:
response = self.session.get(url) response = self.session.get(url)
......
...@@ -9,7 +9,8 @@ from .repository import Repository ...@@ -9,7 +9,8 @@ from .repository import Repository
if TYPE_CHECKING: if TYPE_CHECKING:
from poetry.core.packages import Package from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Package # noqa
class Pool(BaseRepository): class Pool(BaseRepository):
...@@ -108,12 +109,12 @@ class Pool(BaseRepository): ...@@ -108,12 +109,12 @@ class Pool(BaseRepository):
return self return self
def has_package(self, package): def has_package(self, package): # type: ("Package") -> bool
raise NotImplementedError() raise NotImplementedError()
def package( def package(
self, name, version, extras=None, repository=None self, name, version, extras=None, repository=None
): # type: (str, str, List[str], str) -> Package ): # type: (str, str, List[str], str) -> "Package"
if repository is not None: if repository is not None:
repository = repository.lower() repository = repository.lower()
...@@ -143,9 +144,7 @@ class Pool(BaseRepository): ...@@ -143,9 +144,7 @@ class Pool(BaseRepository):
raise PackageNotFound("Package {} ({}) not found.".format(name, version)) raise PackageNotFound("Package {} ({}) not found.".format(name, version))
def find_packages( def find_packages(self, dependency): # type: ("Dependency") -> List["Package"]
self, dependency,
):
repository = dependency.source_name repository = dependency.source_name
if repository is not None: if repository is not None:
repository = repository.lower() repository = repository.lower()
...@@ -166,7 +165,7 @@ class Pool(BaseRepository): ...@@ -166,7 +165,7 @@ class Pool(BaseRepository):
return packages return packages
def search(self, query): def search(self, query): # type: (str) -> List["Package"]
from .legacy_repository import LegacyRepository from .legacy_repository import LegacyRepository
results = [] results = []
......
...@@ -45,7 +45,9 @@ class PyPiRepository(RemoteRepository): ...@@ -45,7 +45,9 @@ class PyPiRepository(RemoteRepository):
CACHE_VERSION = parse_constraint("1.0.0") CACHE_VERSION = parse_constraint("1.0.0")
def __init__(self, url="https://pypi.org/", disable_cache=False, fallback=True): def __init__(
self, url="https://pypi.org/", disable_cache=False, fallback=True
): # type: (str, bool, bool) -> None
super(PyPiRepository, self).__init__(url.rstrip("/") + "/simple/") super(PyPiRepository, self).__init__(url.rstrip("/") + "/simple/")
self._base_url = url self._base_url = url
...@@ -72,7 +74,7 @@ class PyPiRepository(RemoteRepository): ...@@ -72,7 +74,7 @@ class PyPiRepository(RemoteRepository):
self._name = "PyPI" self._name = "PyPI"
@property @property
def session(self): def session(self): # type: () -> CacheControl
return self._session return self._session
def find_packages(self, dependency): # type: (Dependency) -> List[Package] def find_packages(self, dependency): # type: (Dependency) -> List[Package]
...@@ -156,7 +158,7 @@ class PyPiRepository(RemoteRepository): ...@@ -156,7 +158,7 @@ class PyPiRepository(RemoteRepository):
): # type: (...) -> Package ): # type: (...) -> 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): def search(self, query): # type: (str) -> List[Package]
results = [] results = []
search = {"q": query} search = {"q": query}
...@@ -236,7 +238,7 @@ class PyPiRepository(RemoteRepository): ...@@ -236,7 +238,7 @@ class PyPiRepository(RemoteRepository):
return PackageInfo.load(cached) return PackageInfo.load(cached)
def find_links_for_package(self, package): def find_links_for_package(self, package): # type: (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 []
...@@ -452,5 +454,5 @@ class PyPiRepository(RemoteRepository): ...@@ -452,5 +454,5 @@ class PyPiRepository(RemoteRepository):
def _download(self, url, dest): # type: (str, str) -> None def _download(self, url, dest): # type: (str, str) -> None
return download_file(url, dest, session=self.session) return download_file(url, dest, session=self.session)
def _log(self, msg, level="info"): def _log(self, msg, level="info"): # type: (str, str) -> None
getattr(logger, level)("<debug>{}:</debug> {}".format(self._name, msg)) getattr(logger, level)("<debug>{}:</debug> {}".format(self._name, msg))
from typing import TYPE_CHECKING
from typing import List
from typing import Optional
from poetry.core.semver import VersionConstraint from poetry.core.semver import VersionConstraint
from poetry.core.semver import VersionRange from poetry.core.semver import VersionRange
from poetry.core.semver import parse_constraint from poetry.core.semver import parse_constraint
...@@ -5,8 +9,16 @@ from poetry.core.semver import parse_constraint ...@@ -5,8 +9,16 @@ from poetry.core.semver import parse_constraint
from .base_repository import BaseRepository from .base_repository import BaseRepository
if TYPE_CHECKING:
from poetry.core.packages import Dependency # noqa
from poetry.core.packages import Link # noqa
from poetry.core.packages import Package # noqa
class Repository(BaseRepository): class Repository(BaseRepository):
def __init__(self, packages=None, name=None): def __init__(
self, packages=None, name=None
): # type: (List["Package"], str) -> None
super(Repository, self).__init__() super(Repository, self).__init__()
self._name = name self._name = name
...@@ -18,17 +30,19 @@ class Repository(BaseRepository): ...@@ -18,17 +30,19 @@ class Repository(BaseRepository):
self.add_package(package) self.add_package(package)
@property @property
def name(self): def name(self): # type: () -> str
return self._name return self._name
def package(self, name, version, extras=None): def package(
self, name, version, extras=None
): # type: (str, str, Optional[List[str]]) -> "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): def find_packages(self, dependency): # type: ("Dependency") -> List["Package"]
constraint = dependency.constraint constraint = dependency.constraint
packages = [] packages = []
ignored_pre_release_packages = [] ignored_pre_release_packages = []
...@@ -71,7 +85,7 @@ class Repository(BaseRepository): ...@@ -71,7 +85,7 @@ class Repository(BaseRepository):
return packages or ignored_pre_release_packages return packages or ignored_pre_release_packages
def has_package(self, package): def has_package(self, package): # type: ("Package") -> bool
package_id = package.unique_name package_id = package.unique_name
for repo_package in self.packages: for repo_package in self.packages:
...@@ -80,10 +94,10 @@ class Repository(BaseRepository): ...@@ -80,10 +94,10 @@ class Repository(BaseRepository):
return False return False
def add_package(self, package): def add_package(self, package): # type: ("Package") -> None
self._packages.append(package) self._packages.append(package)
def remove_package(self, package): def remove_package(self, package): # type: ("Package") -> None
package_id = package.unique_name package_id = package.unique_name
index = None index = None
...@@ -95,10 +109,10 @@ class Repository(BaseRepository): ...@@ -95,10 +109,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): def find_links_for_package(self, package): # type: ("Package") -> List["Link"]
return [] return []
def search(self, query): def search(self, query): # type: (str) -> List["Package"]
results = [] results = []
for package in self.packages: for package in self.packages:
...@@ -107,5 +121,5 @@ class Repository(BaseRepository): ...@@ -107,5 +121,5 @@ class Repository(BaseRepository):
return results return results
def __len__(self): def __len__(self): # type: () -> int
return len(self._packages) return len(self._packages)
...@@ -5,11 +5,19 @@ to suit our purposes. ...@@ -5,11 +5,19 @@ to suit our purposes.
import os import os
import sys import sys
from typing import TYPE_CHECKING
from typing import List
from typing import Union
if TYPE_CHECKING:
from poetry.utils._compat import Path # noqa
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): def expanduser(path): # type: (Union[str, "Path"]) -> str
""" """
Expand ~ and ~user constructions. Expand ~ and ~user constructions.
...@@ -21,7 +29,7 @@ def expanduser(path): ...@@ -21,7 +29,7 @@ def expanduser(path):
return expanded return expanded
def user_cache_dir(appname): def user_cache_dir(appname): # type: (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.
...@@ -64,7 +72,7 @@ def user_cache_dir(appname): ...@@ -64,7 +72,7 @@ def user_cache_dir(appname):
return path return path
def user_data_dir(appname, roaming=False): def user_data_dir(appname, roaming=False): # type: (str, bool) -> 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.
...@@ -104,7 +112,7 @@ def user_data_dir(appname, roaming=False): ...@@ -104,7 +112,7 @@ def user_data_dir(appname, roaming=False):
return path return path
def user_config_dir(appname, roaming=True): def user_config_dir(appname, roaming=True): # type: (str, bool) -> 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.
...@@ -137,7 +145,7 @@ def user_config_dir(appname, roaming=True): ...@@ -137,7 +145,7 @@ def user_config_dir(appname, roaming=True):
# 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): def site_config_dirs(appname): # type: (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.
...@@ -178,7 +186,7 @@ def site_config_dirs(appname): ...@@ -178,7 +186,7 @@ def site_config_dirs(appname):
# -- Windows support functions -- # -- Windows support functions --
def _get_win_folder_from_registry(csidl_name): def _get_win_folder_from_registry(csidl_name): # type: (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_*
...@@ -200,7 +208,7 @@ def _get_win_folder_from_registry(csidl_name): ...@@ -200,7 +208,7 @@ def _get_win_folder_from_registry(csidl_name):
return directory return directory
def _get_win_folder_with_ctypes(csidl_name): def _get_win_folder_with_ctypes(csidl_name): # type: (str) -> str
csidl_const = { csidl_const = {
"CSIDL_APPDATA": 26, "CSIDL_APPDATA": 26,
"CSIDL_COMMON_APPDATA": 35, "CSIDL_COMMON_APPDATA": 35,
...@@ -234,7 +242,7 @@ if WINDOWS: ...@@ -234,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): def _win_path_to_bytes(path): # type: (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
......
...@@ -15,6 +15,7 @@ from pathlib import Path ...@@ -15,6 +15,7 @@ from pathlib import Path
from subprocess import CalledProcessError from subprocess import CalledProcessError
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
...@@ -252,7 +253,7 @@ class SitePackages: ...@@ -252,7 +253,7 @@ class SitePackages:
if value[-1] is True if value[-1] is True
] ]
def __getattr__(self, item): def __getattr__(self, item): # type: (str) -> Any
try: try:
return super(SitePackages, self).__getattribute__(item) return super(SitePackages, self).__getattribute__(item)
except AttributeError: except AttributeError:
...@@ -265,7 +266,9 @@ class EnvError(Exception): ...@@ -265,7 +266,9 @@ class EnvError(Exception):
class EnvCommandError(EnvError): class EnvCommandError(EnvError):
def __init__(self, e, input=None): # type: (CalledProcessError) -> None def __init__(
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(
...@@ -277,7 +280,7 @@ class EnvCommandError(EnvError): ...@@ -277,7 +280,7 @@ class EnvCommandError(EnvError):
class NoCompatiblePythonVersionFound(EnvError): class NoCompatiblePythonVersionFound(EnvError):
def __init__(self, expected, given=None): def __init__(self, expected, given=None): # type: (str, Optional[str]) -> None
if given: if given:
message = ( message = (
"The specified Python version ({}) " "The specified Python version ({}) "
...@@ -618,7 +621,7 @@ class EnvManager(object): ...@@ -618,7 +621,7 @@ class EnvManager(object):
def create_venv( def create_venv(
self, io, name=None, executable=None, force=False self, io, name=None, executable=None, force=False
): # type: (IO, Optional[str], Optional[str], bool) -> Env ): # type: (IO, Optional[str], Optional[str], bool) -> 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
...@@ -849,12 +852,12 @@ class EnvManager(object): ...@@ -849,12 +852,12 @@ class EnvManager(object):
def get_base_prefix(self): # type: () -> Path def get_base_prefix(self): # type: () -> Path
if hasattr(sys, "real_prefix"): if hasattr(sys, "real_prefix"):
return sys.real_prefix return Path(sys.real_prefix)
if hasattr(sys, "base_prefix"): if hasattr(sys, "base_prefix"):
return sys.base_prefix return Path(sys.base_prefix)
return 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, cwd): # type: (str, str) -> str
...@@ -913,7 +916,7 @@ class Env(object): ...@@ -913,7 +916,7 @@ class Env(object):
return self._bin("python") return self._bin("python")
@property @property
def marker_env(self): def marker_env(self): # type: () -> 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()
...@@ -935,7 +938,7 @@ class Env(object): ...@@ -935,7 +938,7 @@ class Env(object):
return os.name return os.name
@property @property
def pip_version(self): def pip_version(self): # type: () -> 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()
...@@ -1009,12 +1012,12 @@ class Env(object): ...@@ -1009,12 +1012,12 @@ class Env(object):
@classmethod @classmethod
def get_base_prefix(cls): # type: () -> Path def get_base_prefix(cls): # type: () -> Path
if hasattr(sys, "real_prefix"): if hasattr(sys, "real_prefix"):
return sys.real_prefix return Path(sys.real_prefix)
if hasattr(sys, "base_prefix"): if hasattr(sys, "base_prefix"):
return sys.base_prefix return Path(sys.base_prefix)
return sys.prefix return Path(sys.prefix)
def get_version_info(self): # type: () -> Tuple[int] def get_version_info(self): # type: () -> Tuple[int]
raise NotImplementedError() raise NotImplementedError()
...@@ -1046,17 +1049,17 @@ class Env(object): ...@@ -1046,17 +1049,17 @@ class Env(object):
""" """
return True return True
def run(self, bin, *args, **kwargs): def run(self, bin, *args, **kwargs): # type: (str, *str, **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): def run_pip(self, *args, **kwargs): # type: (*str, **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): def _run(self, cmd, **kwargs): # type: (List[str], **Any) -> Union[int, str]
""" """
Run a command inside the Python environment. Run a command inside the Python environment.
""" """
...@@ -1077,7 +1080,7 @@ class Env(object): ...@@ -1077,7 +1080,7 @@ class Env(object):
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
input=encode(input_), input=encode(input_),
check=True, check=True,
**kwargs **kwargs,
).stdout ).stdout
elif call: elif call:
return subprocess.call(cmd, stderr=subprocess.STDOUT, **kwargs) return subprocess.call(cmd, stderr=subprocess.STDOUT, **kwargs)
...@@ -1090,7 +1093,9 @@ class Env(object): ...@@ -1090,7 +1093,9 @@ class Env(object):
return decode(output) return decode(output)
def execute(self, bin, *args, **kwargs): def execute(
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:
...@@ -1145,7 +1150,7 @@ class Env(object): ...@@ -1145,7 +1150,7 @@ class Env(object):
def __eq__(self, other): # type: (Env) -> bool def __eq__(self, other): # type: (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): def __repr__(self): # type: () -> str
return '{}("{}")'.format(self.__class__.__name__, self._path) return '{}("{}")'.format(self.__class__.__name__, self._path)
...@@ -1332,11 +1337,11 @@ class VirtualEnv(Env): ...@@ -1332,11 +1337,11 @@ class VirtualEnv(Env):
def is_venv(self): # type: () -> bool def is_venv(self): # type: () -> bool
return True return True
def is_sane(self): def is_sane(self): # type: () -> 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): def _run(self, cmd, **kwargs): # type: (List[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)
...@@ -1346,7 +1351,9 @@ class VirtualEnv(Env): ...@@ -1346,7 +1351,9 @@ class VirtualEnv(Env):
return super(VirtualEnv, self)._run(cmd, **kwargs) return super(VirtualEnv, self)._run(cmd, **kwargs)
def execute(self, bin, *args, **kwargs): def execute(
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)
...@@ -1357,7 +1364,7 @@ class VirtualEnv(Env): ...@@ -1357,7 +1364,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): def temp_environ(self): # type: () -> Iterator[None]
environ = dict(os.environ) environ = dict(os.environ)
try: try:
yield yield
...@@ -1365,16 +1372,18 @@ class VirtualEnv(Env): ...@@ -1365,16 +1372,18 @@ class VirtualEnv(Env):
os.environ.clear() os.environ.clear()
os.environ.update(environ) os.environ.update(environ)
def unset_env(self, key): def unset_env(self, key): # type: (str) -> None
if key in os.environ: if key in os.environ:
del os.environ[key] del os.environ[key]
def _updated_path(self): def _updated_path(self): # type: () -> 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__(self, path=None, base=None, execute=False): def __init__(
self, path=None, base=None, execute=False
): # type: (Path, Optional[Path], bool) -> None
if path is None: if path is None:
path = Path(sys.prefix) path = Path(sys.prefix)
...@@ -1386,35 +1395,37 @@ class NullEnv(SystemEnv): ...@@ -1386,35 +1395,37 @@ class NullEnv(SystemEnv):
def get_pip_command(self): # type: () -> List[str] def get_pip_command(self): # type: () -> List[str]
return [self._bin("python"), "-m", "pip"] return [self._bin("python"), "-m", "pip"]
def _run(self, cmd, **kwargs): def _run(self, cmd, **kwargs): # type: (List[str], **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(self, bin, *args, **kwargs): def execute(
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): def _bin(self, bin): # type: (str) -> str
return bin return bin
class MockEnv(NullEnv): class MockEnv(NullEnv):
def __init__( def __init__(
self, self,
version_info=(3, 7, 0), version_info=(3, 7, 0), # type: Tuple[int, int, int]
python_implementation="CPython", python_implementation="CPython", # type: str
platform="darwin", platform="darwin", # type: str
os_name="posix", os_name="posix", # type: str
is_venv=False, is_venv=False, # type: bool
pip_version="19.1", pip_version="19.1", # type: str
sys_path=None, sys_path=None, # type: Optional[List[str]]
marker_env=None, marker_env=None, # type: Dict[str, Any]
supported_tags=None, supported_tags=None, # type: List[Tag]
**kwargs **kwargs, # type: Any
): ):
super(MockEnv, self).__init__(**kwargs) super(MockEnv, self).__init__(**kwargs)
...@@ -1437,11 +1448,11 @@ class MockEnv(NullEnv): ...@@ -1437,11 +1448,11 @@ class MockEnv(NullEnv):
return self._os_name return self._os_name
@property @property
def pip_version(self): def pip_version(self): # type: () -> Version
return self._pip_version return self._pip_version
@property @property
def sys_path(self): def sys_path(self): # type: () -> 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
......
from typing import Iterable
from typing import Iterator from typing import Iterator
from typing import List from typing import List
from typing import Mapping from typing import Mapping
...@@ -36,7 +37,7 @@ def get_extra_package_names( ...@@ -36,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): def _extra_packages(package_names): # type: (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:
......
...@@ -6,6 +6,10 @@ import tempfile ...@@ -6,6 +6,10 @@ import tempfile
from contextlib import contextmanager from contextlib import contextmanager
from pathlib import Path from pathlib import Path
from typing import Any
from typing import Callable
from typing import Dict
from typing import Iterator
from typing import List from typing import List
from typing import Optional from typing import Optional
...@@ -37,13 +41,13 @@ def normalize_version(version): # type: (str) -> str ...@@ -37,13 +41,13 @@ def normalize_version(version): # type: (str) -> str
return str(Version(version)) return str(Version(version))
def _del_ro(action, name, exc): def _del_ro(action, name, exc): # type: (Callable, str, 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): def temporary_directory(*args, **kwargs): # type: (*Any, **Any) -> Iterator[str]
name = tempfile.mkdtemp(*args, **kwargs) name = tempfile.mkdtemp(*args, **kwargs)
yield name yield name
...@@ -67,7 +71,7 @@ def get_client_cert(config, repository_name): # type: (Config, str) -> Optional ...@@ -67,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): def _on_rm_error(func, path, exc_info): # type: (Callable, str, Exception) -> None
if not os.path.exists(path): if not os.path.exists(path):
return return
...@@ -75,14 +79,14 @@ def _on_rm_error(func, path, exc_info): ...@@ -75,14 +79,14 @@ def _on_rm_error(func, path, exc_info):
func(path) func(path)
def safe_rmtree(path): def safe_rmtree(path): # type: (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): def merge_dicts(d1, d2): # type: (Dict, 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])
......
import logging import logging
from typing import TYPE_CHECKING
from typing import Dict
from typing import Optional
if TYPE_CHECKING:
from poetry.config.config import Config # noqa
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -15,16 +22,16 @@ class KeyRingError(Exception): ...@@ -15,16 +22,16 @@ class KeyRingError(Exception):
class KeyRing: class KeyRing:
def __init__(self, namespace): def __init__(self, namespace): # type: (str) -> None
self._namespace = namespace self._namespace = namespace
self._is_available = True self._is_available = True
self._check() self._check()
def is_available(self): def is_available(self): # type: () -> bool
return self._is_available return self._is_available
def get_password(self, name, username): def get_password(self, name, username): # type: (str, str) -> Optional[str]
if not self.is_available(): if not self.is_available():
return return
...@@ -40,7 +47,7 @@ class KeyRing: ...@@ -40,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): def set_password(self, name, username, password): # type: (str, str, str) -> None
if not self.is_available(): if not self.is_available():
return return
...@@ -58,7 +65,7 @@ class KeyRing: ...@@ -58,7 +65,7 @@ class KeyRing:
) )
) )
def delete_password(self, name, username): def delete_password(self, name, username): # type: (str, str) -> None
if not self.is_available(): if not self.is_available():
return return
...@@ -74,10 +81,10 @@ class KeyRing: ...@@ -74,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): def get_entry_name(self, name): # type: (str) -> str
return "{}-{}".format(self._namespace, name) return "{}-{}".format(self._namespace, name)
def _check(self): def _check(self): # type: () -> None
try: try:
import keyring import keyring
except Exception as e: except Exception as e:
...@@ -113,12 +120,12 @@ class KeyRing: ...@@ -113,12 +120,12 @@ class KeyRing:
class PasswordManager: class PasswordManager:
def __init__(self, config): def __init__(self, config): # type: ("Config") -> None
self._config = config self._config = config
self._keyring = None self._keyring = None
@property @property
def keyring(self): def keyring(self): # type: () -> 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():
...@@ -128,7 +135,7 @@ class PasswordManager: ...@@ -128,7 +135,7 @@ class PasswordManager:
return self._keyring return self._keyring
def set_pypi_token(self, name, token): def set_pypi_token(self, name, token): # type: (str, 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
...@@ -136,13 +143,13 @@ class PasswordManager: ...@@ -136,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): def get_pypi_token(self, name): # type: (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): def delete_pypi_token(self, name): # type: (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)
...@@ -150,7 +157,7 @@ class PasswordManager: ...@@ -150,7 +157,7 @@ class PasswordManager:
self.keyring.delete_password(name, "__token__") self.keyring.delete_password(name, "__token__")
def get_http_auth(self, name): def get_http_auth(self, name): # type: (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))
...@@ -167,7 +174,9 @@ class PasswordManager: ...@@ -167,7 +174,9 @@ class PasswordManager:
"password": password, "password": password,
} }
def set_http_password(self, name, username, password): def set_http_password(
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():
...@@ -177,7 +186,7 @@ class PasswordManager: ...@@ -177,7 +186,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): def delete_http_password(self, name): # type: (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
......
...@@ -356,7 +356,9 @@ class SetupReader(object): ...@@ -356,7 +356,9 @@ class SetupReader(object):
if target.id == name: if target.id == name:
return elem.value return elem.value
def _find_in_dict(self, dict_, name): # type: (ast.Call, str) -> Optional[Any] def _find_in_dict(
self, dict_, name
): # type: (Union[ast.Dict, ast.Call], str) -> 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
...@@ -3,6 +3,7 @@ import signal ...@@ -3,6 +3,7 @@ import signal
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Any
import pexpect import pexpect
...@@ -78,7 +79,7 @@ class Shell: ...@@ -78,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): def resize(sig, data): # type: (Any, Any) -> None
terminal = Terminal() terminal = Terminal()
c.setwinsize(terminal.height, terminal.width) c.setwinsize(terminal.height, terminal.width)
...@@ -90,7 +91,7 @@ class Shell: ...@@ -90,7 +91,7 @@ class Shell:
sys.exit(c.exitstatus) sys.exit(c.exitstatus)
def _get_activate_script(self): def _get_activate_script(self): # type: () -> str
if "fish" == self._name: if "fish" == self._name:
suffix = ".fish" suffix = ".fish"
elif "csh" == self._name: elif "csh" == self._name:
...@@ -102,7 +103,7 @@ class Shell: ...@@ -102,7 +103,7 @@ class Shell:
return "activate" + suffix return "activate" + suffix
def _get_source_command(self): def _get_source_command(self): # type: () -> str
if "fish" == self._name: if "fish" == self._name:
return "source" return "source"
elif "csh" == self._name: elif "csh" == self._name:
......
from typing import TYPE_CHECKING
from typing import Optional
from typing import Union from typing import Union
from poetry.core.packages import Package from poetry.core.packages import Package
from poetry.core.semver import Version from poetry.core.semver import Version
if TYPE_CHECKING:
from poetry.repositories import Pool # noqa
class VersionSelector(object): class VersionSelector(object):
def __init__(self, pool): def __init__(self, pool): # type: ("Pool") -> None
self._pool = pool self._pool = pool
def find_best_candidate( def find_best_candidate(
self, self,
package_name, # type: str package_name, # type: str
target_package_version=None, # type: Union[str, None] target_package_version=None, # type: Optional[str]
allow_prereleases=False, # type: bool allow_prereleases=False, # type: bool
source=None, # type: str source=None, # type: Optional[str]
): # type: (...) -> Union[Package, bool] ): # type: (...) -> Union[Package, bool]
""" """
Given a package name and optional version, Given a package name and optional version,
...@@ -52,12 +58,12 @@ class VersionSelector(object): ...@@ -52,12 +58,12 @@ class VersionSelector(object):
return False return False
return package return package
def find_recommended_require_version(self, package): def find_recommended_require_version(self, package): # type: (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): def _transform_version(self, version, pretty_version): # type: (str, 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]
......
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