diff --git a/.flake8 b/.flake8 index 130c44c6752..6005a30d32d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,9 @@ [flake8] max-line-length = 88 ignore = E501, E203, W503 -per-file-ignores = __init__.py:F401 +per-file-ignores = + __init__.py:F401 + tests/console/commands/debug/test_resolve.py:W291 exclude = .git __pycache__ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7766f56e108..9377e9a6992 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,26 +1,30 @@ repos: - repo: https://github.com/psf/black - rev: 19.10b0 + rev: 20.8b1 hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.3 + rev: 3.8.4 hooks: - id: flake8 - repo: https://github.com/timothycrosley/isort - rev: 5.4.2 + rev: 5.7.0 hooks: - id: isort additional_dependencies: [toml] exclude: ^.*/?setup\.py$ - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v3.4.0 hooks: - id: trailing-whitespace - exclude: ^tests/.*/fixtures/.* + exclude: | + (?x)( + ^tests/.*/fixtures/.* + | ^tests/console/commands/debug/test_resolve.py + ) - id: end-of-file-fixer exclude: ^tests/.*/fixtures/.* - id: debug-statements diff --git a/poetry.lock b/poetry.lock index b066ade9a7c..6a04096460f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -95,27 +95,15 @@ python-versions = "*" [[package]] name = "cleo" -version = "0.8.1" +version = "1.0.0a1" description = "Cleo allows you to create beautiful and testable command-line interfaces." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -clikit = ">=0.6.0,<0.7.0" - -[[package]] -name = "clikit" -version = "0.6.2" -description = "CliKit is a group of utilities to build beautiful and testable command line interfaces." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6,<4.0" [package.dependencies] -crashtest = {version = ">=0.3.0,<0.4.0", markers = "python_version >= \"3.6\" and python_version < \"4.0\""} -pastel = ">=0.2.0,<0.3.0" -pylev = ">=1.3,<2.0" +crashtest = ">=0.3.1,<0.4.0" +pylev = ">=1.3.0,<2.0.0" [[package]] name = "colorama" @@ -326,14 +314,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" pyparsing = ">=2.0.2" six = "*" -[[package]] -name = "pastel" -version = "0.2.1" -description = "Bring colors to your terminal." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - [[package]] name = "pexpect" version = "4.8.0" @@ -688,7 +668,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.6" -content-hash = "077bd512e57f2e31d9f8b72b9a8b3a918f6844afdd3c7e25c2babc7f95fdfc4e" +content-hash = "c495920c853f794d4046d2d4cc47410ea076d4647e54fd3364e46051d5f18da3" [metadata.files] appdirs = [ @@ -762,12 +742,8 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] cleo = [ - {file = "cleo-0.8.1-py2.py3-none-any.whl", hash = "sha256:141cda6dc94a92343be626bb87a0b6c86ae291dfc732a57bf04310d4b4201753"}, - {file = "cleo-0.8.1.tar.gz", hash = "sha256:3d0e22d30117851b45970b6c14aca4ab0b18b1b53c8af57bed13208147e4069f"}, -] -clikit = [ - {file = "clikit-0.6.2-py2.py3-none-any.whl", hash = "sha256:71268e074e68082306e23d7369a7b99f824a0ef926e55ba2665e911f7208489e"}, - {file = "clikit-0.6.2.tar.gz", hash = "sha256:442ee5db9a14120635c5990bcdbfe7c03ada5898291f0c802f77be71569ded59"}, + {file = "cleo-1.0.0a1-py3-none-any.whl", hash = "sha256:e4a45adc6b56a04d350e7b4893352fdcc07d89d35991e5df16753e05a7c78c2b"}, + {file = "cleo-1.0.0a1.tar.gz", hash = "sha256:45bc5f04278c2f183c7ab77b3ec20f5204711fecb37ae688424c39ea8badf3fe"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -912,10 +888,6 @@ packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, ] -pastel = [ - {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, - {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, -] pexpect = [ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, diff --git a/poetry/__main__.py b/poetry/__main__.py index b280ed84e4a..1c442536107 100644 --- a/poetry/__main__.py +++ b/poetry/__main__.py @@ -2,6 +2,6 @@ if __name__ == "__main__": - from .console import main + from .console.application import main sys.exit(main()) diff --git a/poetry/console/__init__.py b/poetry/console/__init__.py index c0c25738482..e69de29bb2d 100644 --- a/poetry/console/__init__.py +++ b/poetry/console/__init__.py @@ -1,5 +0,0 @@ -from .application import Application - - -def main(): - return Application().run() diff --git a/poetry/console/application.py b/poetry/console/application.py index 027fec85776..27874236761 100644 --- a/poetry/console/application.py +++ b/poetry/console/application.py @@ -1,62 +1,94 @@ -import sys +import logging +import re -from cleo import Application as BaseApplication +from importlib import import_module +from typing import Any +from typing import Callable +from typing import Optional +from typing import cast + +from cleo.application import Application as BaseApplication +from cleo.events.console_command_event import ConsoleCommandEvent +from cleo.events.console_events import COMMAND +from cleo.events.event_dispatcher import EventDispatcher +from cleo.exceptions import CleoException +from cleo.formatters.style import Style +from cleo.io.inputs.argv_input import ArgvInput +from cleo.io.inputs.input import Input +from cleo.io.io import IO +from cleo.io.outputs.output import Output +from cleo.loaders.factory_command_loader import FactoryCommandLoader from poetry.__version__ import __version__ -from .commands.about import AboutCommand -from .commands.add import AddCommand -from .commands.build import BuildCommand -from .commands.cache.cache import CacheCommand -from .commands.check import CheckCommand -from .commands.config import ConfigCommand -from .commands.debug.debug import DebugCommand -from .commands.env.env import EnvCommand -from .commands.export import ExportCommand -from .commands.init import InitCommand -from .commands.install import InstallCommand -from .commands.lock import LockCommand -from .commands.new import NewCommand -from .commands.publish import PublishCommand -from .commands.remove import RemoveCommand -from .commands.run import RunCommand -from .commands.search import SearchCommand -from .commands.self.self import SelfCommand -from .commands.shell import ShellCommand -from .commands.show import ShowCommand -from .commands.update import UpdateCommand -from .commands.version import VersionCommand -from .config import ApplicationConfig +from .commands.command import Command + + +def load_command(name: str) -> Callable: + def _load(): + module = import_module( + "poetry.console.commands.{}".format(".".join(name.split(" "))) + ) + command_class = getattr( + module, "{}Command".format("".join(c.title() for c in name.split(" "))) + ) + + return command_class() + + return _load + + +COMMANDS = [ + "about", + "add", + "build", + "check", + "config", + "export", + "init", + "install", + "lock", + "new", + "publish", + "remove", + "run", + "search", + "shell", + "show", + "update", + "version", + # Cache commands + "cache clear", + "cache list", + # Debug commands + "debug info", + "debug resolve", + # Env commands + "env info", + "env list", + "env remove", + "env use", + # Self commands + "self update", +] class Application(BaseApplication): def __init__(self): - super(Application, self).__init__( - "poetry", __version__, config=ApplicationConfig("poetry", __version__) - ) + super(Application, self).__init__("poetry", __version__) self._poetry = None - for command in self.get_default_commands(): - self.add(command) - - if sys.version_info[:2] < (3, 6): - python_version = "{}".format( - ".".join(str(v) for v in sys.version_info[:2]) - ) - poetry_feature_release = "1.2" - message = ( - "\n" - "Python {} will no longer be supported " - "in the next feature release of Poetry ({}).\n" - "You should consider updating your Python version to a supported one.\n\n" - "" - "Note that you will still be able to manage Python {} projects " - "by using the env command.\n" - "See https://python-poetry.org/docs/managing-environments/ " - "for more information." - ).format(python_version, poetry_feature_release, python_version) - self._preliminary_io.error_line("{}\n".format(message)) + dispatcher = EventDispatcher() + dispatcher.add_listener(COMMAND, self.register_command_loggers) + dispatcher.add_listener(COMMAND, self.set_env) + dispatcher.add_listener(COMMAND, self.set_installer) + self.set_event_dispatcher(dispatcher) + + command_loader = FactoryCommandLoader( + {name: load_command(name) for name in COMMANDS} + ) + self.set_command_loader(command_loader) @property def poetry(self): @@ -71,45 +103,173 @@ def poetry(self): return self._poetry - def reset_poetry(self): # type: () -> None + def reset_poetry(self) -> None: self._poetry = None - def get_default_commands(self): # type: () -> list - commands = [ - AboutCommand(), - AddCommand(), - BuildCommand(), - CheckCommand(), - ConfigCommand(), - ExportCommand(), - InitCommand(), - InstallCommand(), - LockCommand(), - NewCommand(), - PublishCommand(), - RemoveCommand(), - RunCommand(), - SearchCommand(), - ShellCommand(), - ShowCommand(), - UpdateCommand(), - VersionCommand(), + def create_io( + self, + input: Optional[Input] = None, + output: Optional[Output] = None, + error_output: Optional[Output] = None, + ) -> IO: + io = super(Application, self).create_io(input, output, error_output) + + # Set our own CLI styles + formatter = io.output.formatter + formatter.set_style("c1", Style("cyan")) + formatter.set_style("c2", Style("default", options=["bold"])) + formatter.set_style("info", Style("blue")) + formatter.set_style("comment", Style("green")) + formatter.set_style("warning", Style("yellow")) + formatter.set_style("debug", Style("default", options=["dark"])) + formatter.set_style("success", Style("green")) + + # Dark variants + formatter.set_style("c1_dark", Style("cyan", options=["dark"])) + formatter.set_style("c2_dark", Style("default", options=["bold", "dark"])) + formatter.set_style("success_dark", Style("green", options=["dark"])) + + io.output.set_formatter(formatter) + io.error_output.set_formatter(formatter) + + return io + + def _configure_io(self, io: IO) -> None: + # We need to check if the command being run + # is the "run" command. + definition = self.definition + try: + io.input.bind(definition) + except CleoException: + pass + + name = io.input.first_argument + if name == "run": + from .io.inputs.run_argv_input import RunArgvInput + + input = cast(ArgvInput, io.input) + run_input = RunArgvInput([self._name or ""] + input._tokens) + # For the run command reset the definition + # with only the set options (i.e. the options given before the command) + for option_name, value in input.options.items(): + if value: + option = definition.option(option_name) + run_input.add_parameter_option("--" + option.name) + if option.shortcut: + shortcuts = re.split(r"\|-?", option.shortcut.lstrip("-")) + shortcuts = [s for s in shortcuts if s] + for shortcut in shortcuts: + run_input.add_parameter_option("-" + shortcut.lstrip("-")) + + try: + run_input.bind(definition) + except CleoException: + pass + + for option_name, value in input.options.items(): + if value: + run_input.set_option(option_name, value) + + io.set_input(run_input) + + return super()._configure_io(io) + + def register_command_loggers( + self, event: ConsoleCommandEvent, event_name: str, _: Any + ) -> None: + from .logging.io_formatter import IOFormatter + from .logging.io_handler import IOHandler + + command = event.command + if not isinstance(command, Command): + return + + io = event.io + + loggers = [ + "poetry.packages.locker", + "poetry.packages.package", + "poetry.utils.password_manager", ] - # Cache commands - commands += [CacheCommand()] + loggers += command.loggers + + handler = IOHandler(io) + handler.setFormatter(IOFormatter()) + + for logger in loggers: + logger = logging.getLogger(logger) + + logger.handlers = [handler] + + level = logging.WARNING + # The builders loggers are special and we can actually + # start at the INFO level. + if logger.name.startswith("poetry.core.masonry.builders"): + level = logging.INFO + + if io.is_debug(): + level = logging.DEBUG + elif io.is_very_verbose() or io.is_verbose(): + level = logging.INFO + + logger.setLevel(level) + + def set_env(self, event: ConsoleCommandEvent, event_name: str, _: Any): + from .commands.env_command import EnvCommand - # Debug command - commands += [DebugCommand()] + command: EnvCommand = cast(EnvCommand, event.command) + if not isinstance(command, EnvCommand): + return - # Env command - commands += [EnvCommand()] + if command.env is not None: + return + + from poetry.utils.env import EnvManager + + io = event.io + poetry = command.poetry + + env_manager = EnvManager(poetry) + env = env_manager.create_venv(io) + + if env.is_venv() and io.is_verbose(): + io.write_line("Using virtualenv: {}".format(env.path)) + + command.set_env(env) + + def set_installer( + self, event: ConsoleCommandEvent, event_name: str, _: Any + ) -> None: + from .commands.installer_command import InstallerCommand + + command: InstallerCommand = cast(InstallerCommand, event.command) + if not isinstance(command, InstallerCommand): + return + + # If the command already has an installer + # we skip this step + if command.installer is not None: + return + + from poetry.installation.installer import Installer + + poetry = command.poetry + installer = Installer( + event.io, + command.env, + poetry.package, + poetry.locker, + poetry.pool, + poetry.config, + ) + installer.use_executor(poetry.config.get("experimental.new-installer", False)) + command.set_installer(installer) - # Self commands - commands += [SelfCommand()] - return commands +def main(): + return Application().run() if __name__ == "__main__": - Application().run() + main() diff --git a/poetry/console/commands/__init__.py b/poetry/console/commands/__init__.py index b8cb3f4e1f4..e69de29bb2d 100644 --- a/poetry/console/commands/__init__.py +++ b/poetry/console/commands/__init__.py @@ -1,18 +0,0 @@ -from .about import AboutCommand -from .add import AddCommand -from .build import BuildCommand -from .check import CheckCommand -from .config import ConfigCommand -from .export import ExportCommand -from .init import InitCommand -from .install import InstallCommand -from .lock import LockCommand -from .new import NewCommand -from .publish import PublishCommand -from .remove import RemoveCommand -from .run import RunCommand -from .search import SearchCommand -from .shell import ShellCommand -from .show import ShowCommand -from .update import UpdateCommand -from .version import VersionCommand diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index 72ddeb015c1..dcf8e184e9e 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -2,8 +2,8 @@ from typing import Dict from typing import List -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from .init import InitCommand from .installer_command import InstallerCommand diff --git a/poetry/console/commands/build.py b/poetry/console/commands/build.py index 72b7319fcd5..fc1f57bcfc3 100644 --- a/poetry/console/commands/build.py +++ b/poetry/console/commands/build.py @@ -1,4 +1,4 @@ -from cleo import option +from cleo.helpers import option from .env_command import EnvCommand diff --git a/poetry/console/commands/cache/cache.py b/poetry/console/commands/cache/cache.py deleted file mode 100644 index 695e27e0af7..00000000000 --- a/poetry/console/commands/cache/cache.py +++ /dev/null @@ -1,15 +0,0 @@ -from poetry.console.commands.cache.list import CacheListCommand - -from ..command import Command -from .clear import CacheClearCommand - - -class CacheCommand(Command): - - name = "cache" - description = "Interact with Poetry's cache" - - commands = [CacheClearCommand(), CacheListCommand()] - - def handle(self): - return self.call("help", self._config.name) diff --git a/poetry/console/commands/cache/clear.py b/poetry/console/commands/cache/clear.py index 42e71091526..8d812ef2ee7 100644 --- a/poetry/console/commands/cache/clear.py +++ b/poetry/console/commands/cache/clear.py @@ -1,14 +1,14 @@ import os -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from ..command import Command class CacheClearCommand(Command): - name = "clear" + name = "cache clear" description = "Clears Poetry's cache." arguments = [argument("cache", description="The name of the cache to clear.")] diff --git a/poetry/console/commands/cache/list.py b/poetry/console/commands/cache/list.py index 6a030fa2eba..c6230ee9f62 100644 --- a/poetry/console/commands/cache/list.py +++ b/poetry/console/commands/cache/list.py @@ -5,7 +5,7 @@ class CacheListCommand(Command): - name = "list" + name = "cache list" description = "List Poetry's caches." def handle(self): diff --git a/poetry/console/commands/command.py b/poetry/console/commands/command.py index 1e22142341a..e854933bfe6 100644 --- a/poetry/console/commands/command.py +++ b/poetry/console/commands/command.py @@ -1,4 +1,4 @@ -from cleo import Command as BaseCommand +from cleo.commands.command import Command as BaseCommand class Command(BaseCommand): diff --git a/poetry/console/commands/config.py b/poetry/console/commands/config.py index 310524d4ee2..717aca4a34c 100644 --- a/poetry/console/commands/config.py +++ b/poetry/console/commands/config.py @@ -1,8 +1,8 @@ import json import re -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from poetry.core.pyproject import PyProjectException from poetry.core.toml.file import TOMLFile @@ -70,7 +70,11 @@ def unique_config_values(self): boolean_normalizer, False, ), - "installer.parallel": (boolean_validator, boolean_normalizer, True,), + "installer.parallel": ( + boolean_validator, + boolean_normalizer, + True, + ), } return unique_config_values diff --git a/poetry/console/commands/debug/debug.py b/poetry/console/commands/debug/debug.py deleted file mode 100644 index 468e2faad1f..00000000000 --- a/poetry/console/commands/debug/debug.py +++ /dev/null @@ -1,11 +0,0 @@ -from ..command import Command -from .info import DebugInfoCommand -from .resolve import DebugResolveCommand - - -class DebugCommand(Command): - - name = "debug" - description = "Debug various elements of Poetry." - - commands = [DebugInfoCommand().default(), DebugResolveCommand()] diff --git a/poetry/console/commands/debug/info.py b/poetry/console/commands/debug/info.py index 81096a6ffc8..ef8b044e737 100644 --- a/poetry/console/commands/debug/info.py +++ b/poetry/console/commands/debug/info.py @@ -1,13 +1,11 @@ import sys -from clikit.args import StringArgs - from ..command import Command class DebugInfoCommand(Command): - name = "info" + name = "debug info" description = "Shows debug information." def handle(self): @@ -25,7 +23,6 @@ def handle(self): ] ) ) - args = StringArgs("") - command = self.application.get_command("env").get_sub_command("info") + command = self.application.get("env info") - return command.run(args, self._io) + return command.run(self._io) diff --git a/poetry/console/commands/debug/resolve.py b/poetry/console/commands/debug/resolve.py index 52ae1951b21..95cc959913e 100644 --- a/poetry/console/commands/debug/resolve.py +++ b/poetry/console/commands/debug/resolve.py @@ -1,12 +1,13 @@ -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option +from cleo.io.outputs.output import Verbosity from ..init import InitCommand class DebugResolveCommand(InitCommand): - name = "resolve" + name = "debug resolve" description = "Debugs dependency resolution." arguments = [ @@ -28,9 +29,10 @@ class DebugResolveCommand(InitCommand): loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"] def handle(self): + from cleo.io.null_io import NullIO + from poetry.core.packages.project_package import ProjectPackage from poetry.factory import Factory - from poetry.io.null_io import NullIO from poetry.puzzle import Solver from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository @@ -49,14 +51,12 @@ def handle(self): ) # Silencing output - is_quiet = self.io.output.is_quiet() - if not is_quiet: - self.io.output.set_quiet(True) + verbosity = self.io.output.verbosity + self.io.output.set_verbosity(Verbosity.QUIET) requirements = self._determine_requirements(packages) - if not is_quiet: - self.io.output.set_quiet(False) + self.io.output.set_verbosity(verbosity) for constraint in requirements: name = constraint.pop("name") @@ -101,7 +101,8 @@ def handle(self): return 0 - table = self.table([], style="borderless") + table = self.table([], style="compact") + table.style.set_vertical_border_chars("", " ") rows = [] if self.option("install"): @@ -134,4 +135,4 @@ def handle(self): rows.append(row) table.set_rows(rows) - table.render(self.io) + table.render() diff --git a/poetry/console/commands/env/env.py b/poetry/console/commands/env/env.py deleted file mode 100644 index f979b66e436..00000000000 --- a/poetry/console/commands/env/env.py +++ /dev/null @@ -1,16 +0,0 @@ -from ..command import Command -from .info import EnvInfoCommand -from .list import EnvListCommand -from .remove import EnvRemoveCommand -from .use import EnvUseCommand - - -class EnvCommand(Command): - - name = "env" - description = "Interact with Poetry's project environments." - - commands = [EnvInfoCommand(), EnvListCommand(), EnvRemoveCommand(), EnvUseCommand()] - - def handle(self): # type: () -> int - return self.call("help", self._config.name) diff --git a/poetry/console/commands/env/info.py b/poetry/console/commands/env/info.py index 301d88f9520..b7066bc8c8f 100644 --- a/poetry/console/commands/env/info.py +++ b/poetry/console/commands/env/info.py @@ -1,11 +1,11 @@ -from cleo import option +from cleo.helpers import option from ..command import Command class EnvInfoCommand(Command): - name = "info" + name = "env info" description = "Displays information about the current environment." options = [option("path", "p", "Only display the environment's path.")] diff --git a/poetry/console/commands/env/list.py b/poetry/console/commands/env/list.py index 272a853b976..f75c28ff89b 100644 --- a/poetry/console/commands/env/list.py +++ b/poetry/console/commands/env/list.py @@ -1,11 +1,11 @@ -from cleo import option +from cleo.helpers import option from ..command import Command class EnvListCommand(Command): - name = "list" + name = "env list" description = "Lists all virtualenvs associated with the current project." options = [option("full-path", None, "Output the full paths of the virtualenvs.")] diff --git a/poetry/console/commands/env/remove.py b/poetry/console/commands/env/remove.py index 5f208851deb..6f92f6878c4 100644 --- a/poetry/console/commands/env/remove.py +++ b/poetry/console/commands/env/remove.py @@ -1,11 +1,11 @@ -from cleo import argument +from cleo.helpers import argument from ..command import Command class EnvRemoveCommand(Command): - name = "remove" + name = "env remove" description = "Removes a specific virtualenv associated with the project." arguments = [ diff --git a/poetry/console/commands/env/use.py b/poetry/console/commands/env/use.py index ef9cf3def6b..687225cfc64 100644 --- a/poetry/console/commands/env/use.py +++ b/poetry/console/commands/env/use.py @@ -1,11 +1,11 @@ -from cleo import argument +from cleo.helpers import argument from ..command import Command class EnvUseCommand(Command): - name = "use" + name = "env use" description = "Activates or creates a new virtualenv for the current project." arguments = [argument("python", "The python executable to use.")] diff --git a/poetry/console/commands/export.py b/poetry/console/commands/export.py index 126b657b937..8ba4fe22f8e 100644 --- a/poetry/console/commands/export.py +++ b/poetry/console/commands/export.py @@ -1,4 +1,4 @@ -from cleo import option +from cleo.helpers import option from poetry.utils.exporter import Exporter @@ -50,7 +50,7 @@ def handle(self): elif self.io.is_verbose(): options.append(("-v", None)) - self.call("lock", options) + self.call("lock", " ".join(options)) if not locker.is_fresh(): self.line( diff --git a/poetry/console/commands/init.py b/poetry/console/commands/init.py index ef56484abd1..df35cfc1c5d 100644 --- a/poetry/console/commands/init.py +++ b/poetry/console/commands/init.py @@ -12,7 +12,7 @@ from typing import Tuple from typing import Union -from cleo import option +from cleo.helpers import option from tomlkit import inline_table from poetry.core.pyproject import PyProjectException diff --git a/poetry/console/commands/install.py b/poetry/console/commands/install.py index 6a9ef2cb41d..b8905e9f1be 100644 --- a/poetry/console/commands/install.py +++ b/poetry/console/commands/install.py @@ -1,4 +1,4 @@ -from cleo import option +from cleo.helpers import option from .installer_command import InstallerCommand @@ -20,7 +20,9 @@ class InstallCommand(InstallerCommand): "(implicitly enables --verbose).", ), option( - "remove-untracked", None, "Removes packages not present in the lock file.", + "remove-untracked", + None, + "Removes packages not present in the lock file.", ), option( "extras", @@ -85,7 +87,7 @@ def handle(self): return 0 self.line("") - if not self._io.supports_ansi() or self.io.is_debug(): + if not self._io.output.is_decorated() or self.io.is_debug(): self.line( "Installing the current project: {} ({})".format( self.poetry.package.pretty_name, self.poetry.package.pretty_version @@ -104,7 +106,7 @@ def handle(self): builder.build() - if self._io.supports_ansi() and not self.io.is_debug(): + if self._io.output.is_decorated() and not self.io.is_debug(): self.overwrite( "Installing the current project: {} ({})".format( self.poetry.package.pretty_name, self.poetry.package.pretty_version diff --git a/poetry/console/commands/lock.py b/poetry/console/commands/lock.py index 4157c02c5cc..32e62c27bff 100644 --- a/poetry/console/commands/lock.py +++ b/poetry/console/commands/lock.py @@ -1,4 +1,4 @@ -from cleo import option +from cleo.helpers import option from .installer_command import InstallerCommand diff --git a/poetry/console/commands/new.py b/poetry/console/commands/new.py index 4856ff69c96..08a2743d4bd 100644 --- a/poetry/console/commands/new.py +++ b/poetry/console/commands/new.py @@ -1,7 +1,7 @@ import sys -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from poetry.utils.helpers import module_name diff --git a/poetry/console/commands/publish.py b/poetry/console/commands/publish.py index 98d4165fd8d..1b63b56352c 100644 --- a/poetry/console/commands/publish.py +++ b/poetry/console/commands/publish.py @@ -1,6 +1,6 @@ from pathlib import Path -from cleo import option +from cleo.helpers import option from .command import Command diff --git a/poetry/console/commands/remove.py b/poetry/console/commands/remove.py index d9a289cba7f..a55263e53ff 100644 --- a/poetry/console/commands/remove.py +++ b/poetry/console/commands/remove.py @@ -1,5 +1,5 @@ -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from .installer_command import InstallerCommand diff --git a/poetry/console/commands/run.py b/poetry/console/commands/run.py index 46202c52c37..5b7fd7a0138 100644 --- a/poetry/console/commands/run.py +++ b/poetry/console/commands/run.py @@ -1,4 +1,4 @@ -from cleo import argument +from cleo.helpers import argument from .env_command import EnvCommand @@ -12,13 +12,6 @@ class RunCommand(EnvCommand): argument("args", "The command and arguments/options to run.", multiple=True) ] - def __init__(self): # type: () -> None - from poetry.console.args.run_args_parser import RunArgsParser - - super(RunCommand, self).__init__() - - self.config.set_args_parser(RunArgsParser()) - def handle(self): args = self.argument("args") script = args[0] @@ -29,6 +22,17 @@ def handle(self): return self.env.execute(*args) + @property + def _module(self): + from poetry.core.masonry.utils.module import Module + + poetry = self.poetry + package = poetry.package + path = poetry.file.parent + module = Module(package.name, path.as_posix(), package.packages) + + return module + def run_script(self, script, args): if isinstance(script, dict): script = script["callable"] diff --git a/poetry/console/commands/search.py b/poetry/console/commands/search.py index 299dee6a96a..31db25041d5 100644 --- a/poetry/console/commands/search.py +++ b/poetry/console/commands/search.py @@ -1,4 +1,4 @@ -from cleo import argument +from cleo.helpers import argument from .command import Command diff --git a/poetry/console/commands/self/self.py b/poetry/console/commands/self/self.py deleted file mode 100644 index 3e5cafa9180..00000000000 --- a/poetry/console/commands/self/self.py +++ /dev/null @@ -1,13 +0,0 @@ -from ..command import Command -from .update import SelfUpdateCommand - - -class SelfCommand(Command): - - name = "self" - description = "Interact with Poetry directly." - - commands = [SelfUpdateCommand()] - - def handle(self): - return self.call("help", self._config.name) diff --git a/poetry/console/commands/self/update.py b/poetry/console/commands/self/update.py index 7d477ddce16..2f065fcc5e0 100644 --- a/poetry/console/commands/self/update.py +++ b/poetry/console/commands/self/update.py @@ -12,9 +12,10 @@ from functools import cmp_to_key from gzip import GzipFile -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option +from poetry.console.exceptions import PoetrySimpleConsoleException from poetry.core.packages import Dependency from ..command import Command @@ -51,7 +52,7 @@ class SelfUpdateCommand(Command): - name = "update" + name = "self update" description = "Updates Poetry to the latest version." arguments = [argument("version", "The version to update to.", optional=True)] @@ -245,9 +246,9 @@ def _check_recommended_installation(self): try: current.relative_to(self.home) except ValueError: - raise RuntimeError( - "Poetry was not installed with the recommended installer. " - "Cannot update automatically." + raise PoetrySimpleConsoleException( + "Poetry was not installed with the recommended installer, " + "so it cannot be updated automatically." ) def _get_release_name(self, version): diff --git a/poetry/console/commands/show.py b/poetry/console/commands/show.py index 86be1ae7a36..bb5729fb3f5 100644 --- a/poetry/console/commands/show.py +++ b/poetry/console/commands/show.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from .env_command import EnvCommand @@ -33,9 +33,9 @@ class ShowCommand(EnvCommand): colors = ["cyan", "yellow", "green", "magenta", "blue"] def handle(self): - from clikit.utils.terminal import Terminal + from cleo.io.null_io import NullIO + from cleo.terminal import Terminal - from poetry.io.null_io import NullIO from poetry.puzzle.solver import Solver from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.pool import Pool @@ -48,7 +48,7 @@ def handle(self): self.init_styles(self.io) if self.option("outdated"): - self._args.set_option("latest", True) + self._io.input.set_option("latest", True) include_dev = not self.option("no-dev") locked_repo = self.poetry.locker.locked_repository(True) @@ -68,7 +68,6 @@ def handle(self): return 0 table = self.table(style="compact") - # table.style.line_vc_char = "" locked_packages = locked_repo.packages pool = Pool(ignore_repository_names=True) pool.add_repository(locked_repo) @@ -141,7 +140,7 @@ def handle(self): continue current_length = len(locked.pretty_name) - if not self._io.output.supports_ansi(): + if not self._io.output.is_decorated(): installed_status = self.get_installed_status(locked, installed_repo) if installed_status == "not-installed": @@ -204,7 +203,7 @@ def handle(self): if installed_status == "not-installed": color = "red" - if not self._io.output.supports_ansi(): + if not self._io.output.is_decorated(): # Non installed in non decorated mode install_marker = " (!)" @@ -346,7 +345,7 @@ def _display_tree( ) def _write_tree_line(self, io, line): - if not io.output.supports_ansi(): + if not io.output.supports_utf8(): line = line.replace("└", "`-") line = line.replace("├", "|-") line = line.replace("──", "-") @@ -355,15 +354,15 @@ def _write_tree_line(self, io, line): io.write_line(line) def init_styles(self, io): - from clikit.api.formatter import Style + from cleo.formatters.style import Style for color in self.colors: - style = Style(color).fg(color) - io.output.formatter.add_style(style) - io.error_output.formatter.add_style(style) + style = Style(color) + io.output.formatter.set_style(color, style) + io.error_output.formatter.set_style(color, style) def find_latest_package(self, package, include_dev): - from clikit.io import NullIO + from cleo.io.null_io import NullIO from poetry.puzzle.provider import Provider from poetry.version.version_selector import VersionSelector diff --git a/poetry/console/commands/update.py b/poetry/console/commands/update.py index 9e18feb78b6..3b4c4671764 100644 --- a/poetry/console/commands/update.py +++ b/poetry/console/commands/update.py @@ -1,5 +1,5 @@ -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from .installer_command import InstallerCommand diff --git a/poetry/console/commands/version.py b/poetry/console/commands/version.py index 5ac5c666afb..0014dcd59f4 100644 --- a/poetry/console/commands/version.py +++ b/poetry/console/commands/version.py @@ -1,5 +1,5 @@ -from cleo import argument -from cleo import option +from cleo.helpers import argument +from cleo.helpers import option from .command import Command diff --git a/poetry/console/config/__init__.py b/poetry/console/config/__init__.py deleted file mode 100644 index 14e86b4365b..00000000000 --- a/poetry/console/config/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .application_config import ApplicationConfig diff --git a/poetry/console/config/application_config.py b/poetry/console/config/application_config.py deleted file mode 100644 index 492a2137259..00000000000 --- a/poetry/console/config/application_config.py +++ /dev/null @@ -1,244 +0,0 @@ -import logging - -from typing import Any - -from cleo.config import ApplicationConfig as BaseApplicationConfig -from clikit.api.application.application import Application -from clikit.api.args.raw_args import RawArgs -from clikit.api.event import PRE_HANDLE -from clikit.api.event import PreHandleEvent -from clikit.api.event import PreResolveEvent -from clikit.api.event.event_dispatcher import EventDispatcher -from clikit.api.exceptions import CliKitException -from clikit.api.formatter import Style -from clikit.api.io import Input -from clikit.api.io import InputStream -from clikit.api.io import Output -from clikit.api.io import OutputStream -from clikit.api.io.flags import DEBUG -from clikit.api.io.flags import VERBOSE -from clikit.api.io.flags import VERY_VERBOSE -from clikit.api.io.io import IO -from clikit.formatter import AnsiFormatter -from clikit.formatter import PlainFormatter -from clikit.io.input_stream import StandardInputStream -from clikit.io.output_stream import ErrorOutputStream -from clikit.io.output_stream import StandardOutputStream - -from poetry.console.commands.command import Command -from poetry.console.commands.env_command import EnvCommand -from poetry.console.commands.installer_command import InstallerCommand -from poetry.console.logging.io_formatter import IOFormatter -from poetry.console.logging.io_handler import IOHandler -from poetry.mixology.solutions.providers import PythonRequirementSolutionProvider - - -class ApplicationConfig(BaseApplicationConfig): - def configure(self): - super(ApplicationConfig, self).configure() - - self.add_style(Style("c1").fg("cyan")) - self.add_style(Style("c2").fg("default").bold()) - self.add_style(Style("info").fg("blue")) - self.add_style(Style("comment").fg("green")) - self.add_style(Style("error").fg("red").bold()) - self.add_style(Style("warning").fg("yellow").bold()) - self.add_style(Style("debug").fg("default").dark()) - self.add_style(Style("success").fg("green")) - - # Dark variants - self.add_style(Style("c1_dark").fg("cyan").dark()) - self.add_style(Style("c2_dark").fg("default").bold().dark()) - self.add_style(Style("success_dark").fg("green").dark()) - - self.add_event_listener(PRE_HANDLE, self.register_command_loggers) - self.add_event_listener(PRE_HANDLE, self.set_env) - self.add_event_listener(PRE_HANDLE, self.set_installer) - - self._solution_provider_repository.register_solution_providers( - [PythonRequirementSolutionProvider] - ) - - def register_command_loggers( - self, event, event_name, _ - ): # type: (PreHandleEvent, str, Any) -> None - command = event.command.config.handler - if not isinstance(command, Command): - return - - io = event.io - - loggers = [ - "poetry.packages.locker", - "poetry.packages.package", - "poetry.utils.password_manager", - ] - - loggers += command.loggers - - handler = IOHandler(io) - handler.setFormatter(IOFormatter()) - - for logger in loggers: - logger = logging.getLogger(logger) - - logger.handlers = [handler] - - level = logging.WARNING - # The builders loggers are special and we can actually - # start at the INFO level. - if logger.name.startswith("poetry.core.masonry.builders"): - level = logging.INFO - - if io.is_debug(): - level = logging.DEBUG - elif io.is_very_verbose() or io.is_verbose(): - level = logging.INFO - - logger.setLevel(level) - - def set_env(self, event, event_name, _): # type: (PreHandleEvent, str, Any) -> None - from poetry.utils.env import EnvManager - - command = event.command.config.handler # type: EnvCommand - if not isinstance(command, EnvCommand): - return - - if command.env is not None: - return - - io = event.io - poetry = command.poetry - - env_manager = EnvManager(poetry) - env = env_manager.create_venv(io) - - if env.is_venv() and io.is_verbose(): - io.write_line("Using virtualenv: {}".format(env.path)) - - command.set_env(env) - - def set_installer( - self, event, event_name, _ - ): # type: (PreHandleEvent, str, Any) -> None - command = event.command.config.handler # type: InstallerCommand - if not isinstance(command, InstallerCommand): - return - - # If the command already has an installer - # we skip this step - if command.installer is not None: - return - - from poetry.installation.installer import Installer - - poetry = command.poetry - installer = Installer( - event.io, - command.env, - poetry.package, - poetry.locker, - poetry.pool, - poetry.config, - ) - installer.use_executor(poetry.config.get("experimental.new-installer", False)) - command.set_installer(installer) - - def resolve_help_command( - self, event, event_name, dispatcher - ): # type: (PreResolveEvent, str, EventDispatcher) -> None - args = event.raw_args - application = event.application - - if args.has_option_token("-h") or args.has_option_token("--help"): - from clikit.api.resolver import ResolvedCommand - - try: - resolved_command = self.command_resolver.resolve(args, application) - except CliKitException: - # We weren't able to resolve the command, - # due to a parse error most likely, - # so we fall back on the default behavior - return super(ApplicationConfig, self).resolve_help_command( - event, event_name, dispatcher - ) - - # If the current command is the run one, skip option - # check and interpret them as part of the executed command - if resolved_command.command.name == "run": - event.set_resolved_command(resolved_command) - - return event.stop_propagation() - - command = application.get_command("help") - - # Enable lenient parsing - parsed_args = command.parse(args, True) - - event.set_resolved_command(ResolvedCommand(command, parsed_args)) - event.stop_propagation() - - def create_io( - self, - application, - args, - input_stream=None, - output_stream=None, - error_stream=None, - ): # type: (Application, RawArgs, InputStream, OutputStream, OutputStream) -> IO - if input_stream is None: - input_stream = StandardInputStream() - - if output_stream is None: - output_stream = StandardOutputStream() - - if error_stream is None: - error_stream = ErrorOutputStream() - - style_set = application.config.style_set - - if output_stream.supports_ansi(): - output_formatter = AnsiFormatter(style_set) - else: - output_formatter = PlainFormatter(style_set) - - if error_stream.supports_ansi(): - error_formatter = AnsiFormatter(style_set) - else: - error_formatter = PlainFormatter(style_set) - - io = self.io_class( - Input(input_stream), - Output(output_stream, output_formatter), - Output(error_stream, error_formatter), - ) - - resolved_command = application.resolve_command(args) - # If the current command is the run one, skip option - # check and interpret them as part of the executed command - if resolved_command.command.name == "run": - return io - - if args.has_option_token("--no-ansi"): - formatter = PlainFormatter(style_set) - io.output.set_formatter(formatter) - io.error_output.set_formatter(formatter) - elif args.has_option_token("--ansi"): - formatter = AnsiFormatter(style_set, True) - io.output.set_formatter(formatter) - io.error_output.set_formatter(formatter) - - if args.has_option_token("-vvv") or self.is_debug(): - io.set_verbosity(DEBUG) - elif args.has_option_token("-vv"): - io.set_verbosity(VERY_VERBOSE) - elif args.has_option_token("-v"): - io.set_verbosity(VERBOSE) - - if args.has_option_token("--quiet") or args.has_option_token("-q"): - io.set_quiet(True) - - if args.has_option_token("--no-interaction") or args.has_option_token("-n"): - io.set_interactive(False) - - return io diff --git a/poetry/console/exceptions.py b/poetry/console/exceptions.py new file mode 100644 index 00000000000..04e2d84ffa7 --- /dev/null +++ b/poetry/console/exceptions.py @@ -0,0 +1,6 @@ +from cleo.exceptions import CleoSimpleException + + +class PoetrySimpleConsoleException(CleoSimpleException): + + pass diff --git a/poetry/io/__init__.py b/poetry/console/io/__init__.py similarity index 100% rename from poetry/io/__init__.py rename to poetry/console/io/__init__.py diff --git a/poetry/console/io/inputs/__init__.py b/poetry/console/io/inputs/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/poetry/console/io/inputs/run_argv_input.py b/poetry/console/io/inputs/run_argv_input.py new file mode 100644 index 00000000000..e052f3e9c9a --- /dev/null +++ b/poetry/console/io/inputs/run_argv_input.py @@ -0,0 +1,81 @@ +from typing import List +from typing import Optional +from typing import Union + +from cleo.io.inputs.argv_input import ArgvInput +from cleo.io.inputs.definition import Definition + + +class RunArgvInput(ArgvInput): + def __init__( + self, argv: Optional[List[str]] = None, definition: Optional[Definition] = None + ) -> None: + super().__init__(argv, definition=definition) + + self._parameter_options = [] + + @property + def first_argument(self) -> Optional[str]: + return "run" + + def add_parameter_option(self, name: str) -> None: + self._parameter_options.append(name) + + def has_parameter_option( + self, values: Union[str, List[str]], only_params: bool = False + ) -> bool: + if not isinstance(values, list): + values = [values] + + for token in self._tokens: + if only_params and token == "--": + return False + + for value in values: + if value not in self._parameter_options: + continue + + # Options with values: + # For long options, test for '--option=' at beginning + # For short options, test for '-o' at beginning + if value.find("--") == 0: + leading = value + "=" + else: + leading = value + + if token == value or leading != "" and token.find(leading) == 0: + return True + + return False + + def _parse(self) -> None: + parse_options = True + self._parsed = self._tokens[:] + + try: + token = self._parsed.pop(0) + except IndexError: + token = None + + while token is not None: + if parse_options and token == "": + self._parse_argument(token) + elif parse_options and token == "--": + parse_options = False + elif parse_options and token.find("--") == 0: + if token in self._parameter_options: + self._parse_long_option(token) + else: + self._parse_argument(token) + elif parse_options and token[0] == "-" and token != "-": + if token in self._parameter_options: + self._parse_short_option(token) + else: + self._parse_argument(token) + else: + self._parse_argument(token) + + try: + token = self._parsed.pop(0) + except IndexError: + token = None diff --git a/poetry/factory.py b/poetry/factory.py index b38f6da25ae..245cdc43f2c 100644 --- a/poetry/factory.py +++ b/poetry/factory.py @@ -5,14 +5,14 @@ from typing import Dict from typing import Optional -from clikit.api.io.io import IO +from cleo.io.io import IO +from cleo.io.null_io import NullIO from poetry.core.factory import Factory as BaseFactory from poetry.core.toml.file import TOMLFile from .config.config import Config from .config.file_config_source import FileConfigSource -from .io.null_io import NullIO from .locations import CONFIG_DIR from .packages.locker import Locker from .poetry import Poetry diff --git a/poetry/installation/authenticator.py b/poetry/installation/authenticator.py index 1e7a72e751a..f40c03d2b7e 100644 --- a/poetry/installation/authenticator.py +++ b/poetry/installation/authenticator.py @@ -17,7 +17,7 @@ from typing import Optional from typing import Tuple - from clikit.api.io import IO + from cleo.io.io import IO from poetry.config.config import Config diff --git a/poetry/installation/executor.py b/poetry/installation/executor.py index 5523ed2813f..505b1ba9b65 100644 --- a/poetry/installation/executor.py +++ b/poetry/installation/executor.py @@ -10,10 +10,11 @@ from pathlib import Path from subprocess import CalledProcessError +from cleo.io.null_io import NullIO + from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.utils.link import Link from poetry.core.pyproject.toml import PyProjectTOML -from poetry.io.null_io import NullIO from poetry.utils._compat import decode from poetry.utils.env import EnvCommandError from poetry.utils.helpers import safe_rmtree @@ -75,7 +76,7 @@ def removals_count(self): # type: () -> int return self._executed["uninstall"] def supports_fancy_output(self): # type: () -> bool - return self._io.supports_ansi() and not self._dry_run + return self._io.output.is_decorated() and not self._dry_run def disable(self): self._enabled = False @@ -209,13 +210,15 @@ def _execute_operation(self, operation): raise KeyboardInterrupt except Exception as e: try: - from clikit.ui.components.exception_trace import ExceptionTrace + from cleo.ui.exception_trace import ExceptionTrace if not self.supports_fancy_output(): io = self._io else: - message = " {message}: Failed".format( - message=self.get_operation_message(operation, error=True), + message = ( + " {message}: Failed".format( + message=self.get_operation_message(operation, error=True), + ) ) self._write(operation, message) io = self._sections.get(id(operation), self._io) @@ -252,7 +255,8 @@ def _do_execute_operation(self, operation): "Skipped " "for the following reason: " "{reason}".format( - message=operation_message, reason=operation.skip_reason, + message=operation_message, + reason=operation.skip_reason, ), ) @@ -410,8 +414,10 @@ def _execute_update(self, operation): # type: (Update) -> None return self._update(operation) def _execute_uninstall(self, operation): # type: (Uninstall) -> None - message = " • {message}: Removing...".format( - message=self.get_operation_message(operation), + message = ( + " • {message}: Removing...".format( + message=self.get_operation_message(operation), + ) ) self._write(operation, message) @@ -433,8 +439,10 @@ def _install(self, operation): archive = self._download(operation) operation_message = self.get_operation_message(operation) - message = " • {message}: Installing...".format( - message=operation_message, + message = ( + " • {message}: Installing...".format( + message=operation_message, + ) ) self._write(operation, message) @@ -467,8 +475,10 @@ def _remove(self, operation): def _prepare_file(self, operation): package = operation.package - message = " • {message}: Preparing...".format( - message=self.get_operation_message(operation), + message = ( + " • {message}: Preparing...".format( + message=self.get_operation_message(operation), + ) ) self._write(operation, message) @@ -486,8 +496,10 @@ def _install_directory(self, operation): package = operation.package operation_message = self.get_operation_message(operation) - message = " • {message}: Building...".format( - message=operation_message, + message = ( + " • {message}: Building...".format( + message=operation_message, + ) ) self._write(operation, message) @@ -550,8 +562,10 @@ def _install_git(self, operation): package = operation.package operation_message = self.get_operation_message(operation) - message = " • {message}: Cloning...".format( - message=operation_message, + message = ( + " • {message}: Cloning...".format( + message=operation_message, + ) ) self._write(operation, message) @@ -613,18 +627,20 @@ def _download_archive(self, operation, link): # type: (Operation, Link) -> Path ) wheel_size = response.headers.get("content-length") operation_message = self.get_operation_message(operation) - message = " • {message}: Downloading...".format( - message=operation_message, + message = ( + " • {message}: Downloading...".format( + message=operation_message, + ) ) progress = None if self.supports_fancy_output(): if wheel_size is None: self._write(operation, message) else: - from clikit.ui.components.progress_bar import ProgressBar + from cleo.ui.progress_bar import ProgressBar progress = ProgressBar( - self._sections[id(operation)].output, max=int(wheel_size) + self._sections[id(operation)].error_output, max=int(wheel_size) ) progress.set_format(message + " %percent%%") diff --git a/poetry/installation/installer.py b/poetry/installation/installer.py index 2164d39f4b1..0d2721c2c85 100644 --- a/poetry/installation/installer.py +++ b/poetry/installation/installer.py @@ -2,11 +2,11 @@ from typing import Optional from typing import Union -from clikit.api.io import IO +from cleo.io.io import IO +from cleo.io.null_io import NullIO from poetry.config.config import Config from poetry.core.packages.project_package import ProjectPackage -from poetry.io.null_io import NullIO from poetry.packages import Locker from poetry.repositories import Pool from poetry.repositories import Repository diff --git a/poetry/installation/pip_installer.py b/poetry/installation/pip_installer.py index df1249737a1..a2cc962e8d4 100644 --- a/poetry/installation/pip_installer.py +++ b/poetry/installation/pip_installer.py @@ -4,7 +4,7 @@ from subprocess import CalledProcessError -from clikit.api.io import IO +from cleo.io.io import IO from poetry.core.pyproject.toml import PyProjectTOML from poetry.repositories.pool import Pool @@ -177,8 +177,9 @@ def create_temporary_requirement(self, package): return name def install_directory(self, package): + from cleo.io.null_io import NullIO + from poetry.factory import Factory - from poetry.io.null_io import NullIO if package.root_dir: req = (package.root_dir / package.source_url).as_posix() diff --git a/poetry/io/null_io.py b/poetry/io/null_io.py deleted file mode 100644 index d81cd595527..00000000000 --- a/poetry/io/null_io.py +++ /dev/null @@ -1,11 +0,0 @@ -from cleo.io.io_mixin import IOMixin -from clikit.io import NullIO as BaseNullIO - - -class NullIO(IOMixin, BaseNullIO): - """ - A wrapper around CliKit's NullIO. - """ - - def __init__(self, *args, **kwargs): - super(NullIO, self).__init__(*args, **kwargs) diff --git a/poetry/packages/locker.py b/poetry/packages/locker.py index 8cb6d91f916..ae921f4474b 100644 --- a/poetry/packages/locker.py +++ b/poetry/packages/locker.py @@ -347,7 +347,9 @@ def get_project_dependency_packages( if extra_package_names is not None: extra_package_names = set( get_extra_package_names( - repository.packages, self.lock_data.get("extras", {}), extras or (), + repository.packages, + self.lock_data.get("extras", {}), + extras or (), ) ) diff --git a/poetry/publishing/uploader.py b/poetry/publishing/uploader.py index bb1673e3bff..1360335b13a 100644 --- a/poetry/publishing/uploader.py +++ b/poetry/publishing/uploader.py @@ -229,6 +229,8 @@ def _do_upload( def _upload_file( self, session, url, file, dry_run=False ): # type: (requests.Session, str, Path, Optional[bool]) -> requests.Response + from cleo.ui.progress_bar import ProgressBar + data = self.post_data(file) data.update( { @@ -245,7 +247,7 @@ def _upload_file( ("content", (file.name, fp, "application/octet-stream")) ) encoder = MultipartEncoder(data_to_send) - bar = self._io.progress_bar(encoder.len) + bar = ProgressBar(self._io, max=encoder.len) bar.set_format( " - Uploading {0} %percent%%".format(file.name) ) @@ -273,7 +275,7 @@ def _upload_file( ) bar.finish() elif resp.status_code == 301: - if self._io.output.supports_ansi(): + if self._io.output.is_decorated(): self._io.overwrite( " - Uploading {0} {1}".format( file.name, "FAILED" @@ -284,7 +286,7 @@ def _upload_file( "Is the URL missing a trailing slash?" ) except (requests.ConnectionError, requests.HTTPError) as e: - if self._io.output.supports_ansi(): + if self._io.output.is_decorated(): self._io.overwrite( " - Uploading {0} {1}".format( file.name, "FAILED" diff --git a/poetry/puzzle/provider.py b/poetry/puzzle/provider.py index e9719a924d9..038ea0d9c95 100644 --- a/poetry/puzzle/provider.py +++ b/poetry/puzzle/provider.py @@ -1,6 +1,7 @@ import logging import os import re +import time import urllib.parse from contextlib import contextmanager @@ -10,7 +11,7 @@ from typing import List from typing import Optional -from clikit.ui.components import ProgressIndicator +from cleo.ui.progress_indicator import ProgressIndicator from poetry.core.packages import Dependency from poetry.core.packages import DirectoryDependency @@ -42,7 +43,10 @@ class Indicator(ProgressIndicator): - pass + def _formatter_elapsed(self): + elapsed = time.time() - self._start_time + + return "{:.1f}s".format(elapsed) class Provider: @@ -658,8 +662,10 @@ def complete_package( clean_dependencies = [] for dep in dependencies: if not package.dependency.transitive_marker.without_extras().is_any(): - marker_intersection = package.dependency.transitive_marker.without_extras().intersect( - dep.marker.without_extras() + marker_intersection = ( + package.dependency.transitive_marker.without_extras().intersect( + dep.marker.without_extras() + ) ) if marker_intersection.is_empty(): # The dependency is not needed, since the markers specified @@ -772,7 +778,7 @@ def debug(self, message, depth=0): @contextmanager def progress(self): - if not self._io.output.supports_ansi() or self.is_debugging(): + if not self._io.output.is_decorated() or self.is_debugging(): self._io.write_line("Resolving dependencies...") yield else: diff --git a/poetry/puzzle/solver.py b/poetry/puzzle/solver.py index 31858bb3a1d..b18f055eaec 100644 --- a/poetry/puzzle/solver.py +++ b/poetry/puzzle/solver.py @@ -6,7 +6,7 @@ from typing import List from typing import Optional -from clikit.io import ConsoleIO +from cleo.io.io import IO from poetry.core.packages import Package from poetry.core.packages.project_package import ProjectPackage @@ -33,7 +33,7 @@ def __init__( pool, # type: Pool installed, # type: Repository locked, # type: Repository - io, # type: ConsoleIO + io, # type: IO remove_untracked=False, # type: bool provider=None, # type: Optional[Provider] ): @@ -188,7 +188,12 @@ def solve(self, use_latest=None): # type: (...) -> List[Operation] operations.append(Uninstall(installed)) return sorted( - 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): @@ -343,7 +348,12 @@ def dfs_visit(node, back_edges, visited, sorted_nodes): class PackageNode(DFSNode): def __init__( - self, package, packages, previous=None, previous_dep=None, dep=None, + self, + package, + packages, + previous=None, + previous_dep=None, + dep=None, ): self.package = package self.packages = packages diff --git a/poetry/repositories/installed_repository.py b/poetry/repositories/installed_repository.py index 29424dbaeb5..1202d7f6612 100644 --- a/poetry/repositories/installed_repository.py +++ b/poetry/repositories/installed_repository.py @@ -44,7 +44,8 @@ def get_package_paths(cls, env, name): # type: (Env, str) -> Set[Path] # where the pth file for foo-bar might have been installed as either foo-bar.pth or # foo_bar.pth (expected) in either pure or platform lib directories. candidates = itertools.product( - {env.purelib, env.platlib}, {name, module_name(name)}, + {env.purelib, env.platlib}, + {name, module_name(name)}, ) for lib, module in candidates: @@ -110,7 +111,8 @@ def load(cls, env): # type: (Env) -> InstalledRepository for entry in reversed(env.sys_path): for distribution in sorted( - metadata.distributions(path=[entry]), key=lambda d: str(d._path), + metadata.distributions(path=[entry]), + key=lambda d: str(d._path), ): name = distribution.metadata["name"] path = Path(str(distribution._path)) diff --git a/poetry/repositories/pool.py b/poetry/repositories/pool.py index ac712831d3a..4f42698fcde 100644 --- a/poetry/repositories/pool.py +++ b/poetry/repositories/pool.py @@ -144,7 +144,8 @@ def package( raise PackageNotFound("Package {} ({}) not found.".format(name, version)) def find_packages( - self, dependency, + self, + dependency, ): repository = dependency.source_name if repository is not None: diff --git a/poetry/utils/env.py b/poetry/utils/env.py index 22db246911e..eb59d21ef98 100644 --- a/poetry/utils/env.py +++ b/poetry/utils/env.py @@ -24,7 +24,7 @@ import tomlkit import virtualenv -from clikit.api.io import IO +from cleo.io.io import IO from packaging.tags import Tag from packaging.tags import interpreter_name from packaging.tags import interpreter_version diff --git a/poetry/utils/exporter.py b/poetry/utils/exporter.py index f86fdcf19ee..23f7f0f1503 100644 --- a/poetry/utils/exporter.py +++ b/poetry/utils/exporter.py @@ -5,7 +5,7 @@ from typing import Sequence from typing import Union -from clikit.api.io import IO +from cleo.io.io import IO from poetry.poetry import Poetry from poetry.utils._compat import decode diff --git a/pyproject.toml b/pyproject.toml index 412ce84c639..562bfe68901 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,8 +25,7 @@ classifiers = [ python = "^3.6" poetry-core = "^1.0.0" -cleo = "^0.8.1" -clikit = "^0.6.2" +cleo = "^1.0.0a1" crashtest = "^0.3.0" requests = "^2.18" cachy = "^0.3.0" @@ -55,7 +54,7 @@ zipp = { version = "^3.4", python = "<3.8"} urllib3 = "1.25.10" [tool.poetry.scripts] -poetry = "poetry.console:main" +poetry = "poetry.console.application:main" [build-system] diff --git a/sonnet b/sonnet index facbe34e280..090e31ecda2 100755 --- a/sonnet +++ b/sonnet @@ -7,10 +7,31 @@ import sys import tarfile from gzip import GzipFile +from pathlib import Path +from typing import Optional -from cleo import Application -from cleo import Command -from clikit.api.formatter import Style +from cleo.application import Application as BaseApplication +from cleo.commands.command import Command +from cleo.formatters.style import Style +from cleo.helpers import option +from cleo.io.inputs.input import Input +from cleo.io.io import IO +from cleo.io.outputs.output import Output + + +class Application(BaseApplication): + def create_io( + self, + input: Optional[Input] = None, + output: Optional[Output] = None, + error_output: Optional[Output] = None, + ) -> IO: + io = super(Application, self).create_io(input, output, error_output) + + io.output.formatter.set_style("debug", Style("default", options=["dark"])) + io.error_output.formatter.set_style("debug", Style("default", options=["dark"])) + + return io WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") @@ -19,11 +40,12 @@ WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name = class MakeReleaseCommand(Command): """ Makes a self-contained package of Poetry. - - release - {--P|python=?* : Python version to use} """ + name = "make release" + + options = [option("--python", "-P", flag=False, multiple=True)] + PYTHON = { "3.6": "python3.6", "3.7": "python3.7", @@ -52,7 +74,6 @@ class MakeReleaseCommand(Command): from poetry.puzzle import Solver from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository - from poetry.utils._compat import Path from poetry.utils.env import EnvManager from poetry.utils.env import VirtualEnv from poetry.utils.helpers import temporary_directory @@ -244,23 +265,8 @@ class MakeReleaseCommand(Command): return vendor_dir -class MakeCommand(Command): - """ - Build poetry releases. - - make - """ - - commands = [MakeReleaseCommand()] - - def handle(self): - return self.call("help", self.config.name) - - app = Application("sonnet") -app.config.add_style(Style("debug").fg("default").dark()) - -app.add(MakeCommand()) +app.add(MakeReleaseCommand()) if __name__ == "__main__": app.run() diff --git a/tests/conftest.py b/tests/conftest.py index 178a4632b90..d2773c95d56 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,7 @@ import httpretty import pytest -from cleo import CommandTester +from cleo.testers.command_tester import CommandTester from poetry.config.config import Config as BaseConfig from poetry.config.dict_config_source import DictConfigSource @@ -118,7 +118,8 @@ def _pep517_metadata(cls, path): return PackageInfo(name="demo", version="0.1.2") mocker.patch( - "poetry.inspection.info.PackageInfo._pep517_metadata", _pep517_metadata, + "poetry.inspection.info.PackageInfo._pep517_metadata", + _pep517_metadata, ) @@ -224,7 +225,8 @@ def default_python(current_python): @pytest.fixture def repo(http): http.register_uri( - http.GET, re.compile("^https?://foo.bar/(.+?)$"), + http.GET, + re.compile("^https?://foo.bar/(.+?)$"), ) return TestRepository(name="foo") @@ -299,6 +301,13 @@ def _tester(command, poetry=None, installer=None, executor=None, environment=Non command = app.find(command) tester = CommandTester(command) + # Setting the formatter from the application + # TODO: Find a better way to do this in Cleo + app_io = app.create_io() + formatter = app_io.output.formatter + tester.io.output.set_formatter(formatter) + tester.io.error_output.set_formatter(formatter) + if poetry: app._poetry = poetry diff --git a/tests/console/commands/debug/test_resolve.py b/tests/console/commands/debug/test_resolve.py index ffc1e509aef..f3f0db24c6e 100644 --- a/tests/console/commands/debug/test_resolve.py +++ b/tests/console/commands/debug/test_resolve.py @@ -10,7 +10,7 @@ def tester(command_tester_factory): @pytest.fixture(autouse=True) -def __add_packages(repo): +def _add_packages(repo): cachy020 = get_package("cachy", "0.2.0") cachy020.add_dependency(Factory.create_dependency("msgpack-python", ">=0.5 <0.6")) @@ -30,8 +30,8 @@ def test_debug_resolve_gives_resolution_results(tester): Resolution results: -msgpack-python 0.5.3 -cachy 0.2.0 +msgpack-python 0.5.3 +cachy 0.2.0 """ assert expected == tester.io.fetch_output() @@ -46,7 +46,7 @@ def test_debug_resolve_tree_option_gives_the_dependency_tree(tester): Resolution results: cachy 0.2.0 -`-- msgpack-python >=0.5 <0.6 +└── msgpack-python >=0.5 <0.6 """ assert expected == tester.io.fetch_output() @@ -60,8 +60,8 @@ def test_debug_resolve_git_dependency(tester): Resolution results: -pendulum 2.0.3 -demo 0.1.2 +pendulum 2.0.3 +demo 0.1.2 """ assert expected == tester.io.fetch_output() diff --git a/tests/console/commands/env/test_use.py b/tests/console/commands/env/test_use.py index 4ec106b434e..e288bd66003 100644 --- a/tests/console/commands/env/test_use.py +++ b/tests/console/commands/env/test_use.py @@ -40,7 +40,8 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( mocker, tester, venv_cache, venv_name, venvs_in_cache_config ): mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mock_build_env = mocker.patch( @@ -64,7 +65,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( Creating virtualenv {} in {} Using virtualenv: {} """.format( - venv_py37.name, venv_py37.parent, venv_py37, + venv_py37.name, + venv_py37.parent, + venv_py37, ) assert expected == tester.io.fetch_output() @@ -122,7 +125,9 @@ def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var( Creating virtualenv {} in {} Using virtualenv: {} """.format( - venv_dir.name, venv_dir.parent, venv_dir, + venv_dir.name, + venv_dir.parent, + venv_dir, ) assert expected == tester.io.fetch_output() diff --git a/tests/console/commands/self/test_update.py b/tests/console/commands/self/test_update.py index 1598f47865a..2512654dea9 100644 --- a/tests/console/commands/self/test_update.py +++ b/tests/console/commands/self/test_update.py @@ -23,7 +23,7 @@ def test_self_update_should_install_all_necessary_elements( ): os.environ["POETRY_HOME"] = tmp_dir - command = tester._command + command = tester.command version = Version.parse(__version__).next_minor.text mocker.patch( diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index a0811c1c965..6405bc7431c 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -20,7 +20,7 @@ def tester(command_tester_factory): @pytest.fixture() def old_tester(tester): - tester._command.installer.use_executor(False) + tester.command.installer.use_executor(False) return tester @@ -45,7 +45,7 @@ def test_add_no_constraint(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -72,7 +72,7 @@ def test_add_equal_constraint(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count def test_add_greater_constraint(app, repo, tester): @@ -94,7 +94,7 @@ def test_add_greater_constraint(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count def test_add_constraint_with_extras(app, repo, tester): @@ -123,7 +123,7 @@ def test_add_constraint_with_extras(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count def test_add_constraint_dependencies(app, repo, tester): @@ -151,11 +151,11 @@ def test_add_constraint_dependencies(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count def test_add_git_constraint(app, repo, tester, tmp_venv): - tester._command.set_env(tmp_venv) + tester.command.set_env(tmp_venv) repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("cleo", "0.6.5")) @@ -176,7 +176,7 @@ def test_add_git_constraint(app, repo, tester, tmp_venv): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -187,7 +187,7 @@ def test_add_git_constraint(app, repo, tester, tmp_venv): def test_add_git_constraint_with_poetry(app, repo, tester, tmp_venv): - tester._command.set_env(tmp_venv) + tester.command.set_env(tmp_venv) repo.add_package(get_package("pendulum", "1.4.4")) @@ -207,11 +207,11 @@ def test_add_git_constraint_with_poetry(app, repo, tester, tmp_venv): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count def test_add_git_constraint_with_extras(app, repo, tester, tmp_venv): - tester._command.set_env(tmp_venv) + tester.command.set_env(tmp_venv) repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("cleo", "0.6.5")) @@ -235,7 +235,7 @@ def test_add_git_constraint_with_extras(app, repo, tester, tmp_venv): """ assert expected.strip() == tester.io.fetch_output().strip() - assert 4 == tester._command.installer.executor.installations_count + assert 4 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -247,7 +247,7 @@ def test_add_git_constraint_with_extras(app, repo, tester, tmp_venv): def test_add_git_ssh_constraint(app, repo, tester, tmp_venv): - tester._command.set_env(tmp_venv) + tester.command.set_env(tmp_venv) repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("cleo", "0.6.5")) @@ -268,7 +268,7 @@ def test_add_git_ssh_constraint(app, repo, tester, tmp_venv): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -305,7 +305,7 @@ def test_add_directory_constraint(app, repo, tester, mocker): ) assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -338,7 +338,7 @@ def test_add_directory_with_poetry(app, repo, tester, mocker): ) assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count def test_add_file_constraint_wheel(app, repo, tester, mocker, poetry): @@ -366,7 +366,7 @@ def test_add_file_constraint_wheel(app, repo, tester, mocker, poetry): ) assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -401,7 +401,7 @@ def test_add_file_constraint_sdist(app, repo, tester, mocker): ) assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -437,7 +437,7 @@ def test_add_constraint_with_extras_option(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -472,7 +472,7 @@ def test_add_url_constraint_wheel(app, repo, tester, mocker): """ assert expected == tester.io.fetch_output() - assert 2 == tester._command.installer.executor.installations_count + assert 2 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -509,7 +509,7 @@ def test_add_url_constraint_wheel_with_extras(app, repo, tester, mocker): expected = set(expected.splitlines()) output = set(tester.io.fetch_output().splitlines()) assert expected == output - assert 4 == tester._command.installer.executor.installations_count + assert 4 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -541,7 +541,7 @@ def test_add_constraint_with_python(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -573,7 +573,7 @@ def test_add_constraint_with_platform(app, repo, tester, env): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -606,7 +606,7 @@ def test_add_constraint_with_source(app, poetry, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -659,7 +659,7 @@ def test_add_to_section_that_does_no_exist_yet(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] @@ -687,7 +687,7 @@ def test_add_should_not_select_prereleases(app, repo, tester): """ assert expected == tester.io.fetch_output() - assert 1 == tester._command.installer.executor.installations_count + assert 1 == tester.command.installer.executor.installations_count content = app.poetry.file.read()["tool"]["poetry"] diff --git a/tests/console/commands/test_init.py b/tests/console/commands/test_init.py index 812cc23ab96..442a0123284 100644 --- a/tests/console/commands/test_init.py +++ b/tests/console/commands/test_init.py @@ -6,7 +6,7 @@ import pytest -from cleo import CommandTester +from cleo.testers.command_tester import CommandTester from poetry.repositories import Pool from poetry.utils._compat import decode @@ -599,7 +599,7 @@ def test_predefined_and_interactive_dev_dependencies(tester, repo): def test_add_package_with_extras_and_whitespace(tester): - result = tester._command._parse_requirements(["databases[postgresql, sqlite]"]) + result = tester.command._parse_requirements(["databases[postgresql, sqlite]"]) assert result[0]["name"] == "databases" assert len(result[0]["extras"]) == 2 diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py index bcbf4c50006..62671eda624 100644 --- a/tests/console/commands/test_publish.py +++ b/tests/console/commands/test_publish.py @@ -14,16 +14,17 @@ def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http): assert 1 == exit_code - expected = """ + expected_output = """ Publishing simple-project (1.2.3) to PyPI - - +""" + expected_error_output = """\ UploadError HTTP Error 400: Bad Request """ - assert expected in app_tester.io.fetch_output() + assert expected_output in app_tester.io.fetch_output() + assert expected_error_output in app_tester.io.fetch_error() def test_publish_returns_non_zero_code_for_connection_errors(app, app_tester, http): @@ -40,7 +41,7 @@ def request_callback(*_, **__): expected = str(UploadError(error=requests.ConnectionError())) - assert expected in app_tester.io.fetch_output() + assert expected in app_tester.io.fetch_error() def test_publish_with_cert(app_tester, mocker): diff --git a/tests/console/commands/test_run.py b/tests/console/commands/test_run.py index 351d869d1a9..33314fa53c0 100644 --- a/tests/console/commands/test_run.py +++ b/tests/console/commands/test_run.py @@ -11,6 +11,16 @@ def patches(mocker, env): mocker.patch("poetry.utils.env.EnvManager.get", return_value=env) -def test_run_passes_all_args(tester, env): - tester.execute("python -V") +def test_run_passes_all_args(app_tester, env): + app_tester.execute("run python -V") assert [["python", "-V"]] == env.executed + + +def test_run_keeps_options_passed_before_command(app_tester, env): + app_tester.execute("-V --no-ansi run python", decorated=True) + + assert not app_tester.io.is_decorated() + assert app_tester.io.fetch_output() == app_tester.io.remove_format( + app_tester.application.long_version + "\n" + ) + assert [] == env.executed diff --git a/tests/console/commands/test_search.py b/tests/console/commands/test_search.py index 18e094ff1ae..ef668454084 100644 --- a/tests/console/commands/test_search.py +++ b/tests/console/commands/test_search.py @@ -21,7 +21,8 @@ def tester(command_tester_factory): def test_search( - tester, http, + tester, + http, ): tester.execute("sqlalchemy") diff --git a/tests/console/commands/test_show.py b/tests/console/commands/test_show.py index 56e964abfe4..f31c82882ea 100644 --- a/tests/console/commands/test_show.py +++ b/tests/console/commands/test_show.py @@ -1,7 +1,5 @@ import pytest -from clikit.formatter.ansi_formatter import AnsiFormatter - from poetry.factory import Factory from tests.helpers import get_package @@ -186,12 +184,11 @@ def test_show_basic_with_not_installed_packages_decorated(tester, poetry, instal } ) - tester.io.set_formatter(AnsiFormatter(forced=True)) - tester.execute() + tester.execute(decorated=True) expected = """\ -\033[36mcachy \033[0m \033[1m0.1.0\033[0m Cachy package -\033[31mpendulum\033[0m \033[1m2.0.0\033[0m Pendulum package +\033[36mcachy \033[39m \033[39;1m0.1.0\033[39;22m Cachy package +\033[31mpendulum\033[39m \033[39;1m2.0.0\033[39;22m Pendulum package """ assert expected == tester.io.fetch_output() @@ -317,12 +314,11 @@ def test_show_latest_decorated(tester, poetry, installed, repo): } ) - tester.io.set_formatter(AnsiFormatter(forced=True)) - tester.execute("--latest") + tester.execute("--latest", decorated=True) expected = """\ -\033[36mcachy \033[0m \033[1m0.1.0\033[0m \033[33m0.2.0\033[0m Cachy package -\033[36mpendulum\033[0m \033[1m2.0.0\033[0m \033[31m2.0.1\033[0m Pendulum package +\033[36mcachy \033[39m \033[39;1m0.1.0\033[39;22m \033[33m0.2.0\033[39m Cachy package +\033[36mpendulum\033[39m \033[39;1m2.0.0\033[39;22m \033[31m2.0.1\033[39m Pendulum package """ assert expected == tester.io.fetch_output() @@ -1144,7 +1140,7 @@ def test_show_tree(tester, poetry, installed): } ) - tester.execute("--tree") + tester.execute("--tree", supports_utf8=False) expected = """\ cachy 0.2.0 @@ -1215,7 +1211,7 @@ def test_show_tree_no_dev(tester, poetry, installed): expected = """\ cachy 0.2.0 -`-- msgpack-python >=0.5 <0.6 +└── msgpack-python >=0.5 <0.6 """ assert expected == tester.io.fetch_output() diff --git a/tests/console/commands/test_version.py b/tests/console/commands/test_version.py index ac91df1690c..f868d9f1060 100644 --- a/tests/console/commands/test_version.py +++ b/tests/console/commands/test_version.py @@ -1,6 +1,6 @@ import pytest -from poetry.console.commands import VersionCommand +from poetry.console.commands.version import VersionCommand @pytest.fixture() diff --git a/tests/console/conftest.py b/tests/console/conftest.py index a9b06f6c3b2..82143358d4d 100644 --- a/tests/console/conftest.py +++ b/tests/console/conftest.py @@ -4,11 +4,11 @@ import pytest -from cleo import ApplicationTester +from cleo.io.null_io import NullIO +from cleo.testers.application_tester import ApplicationTester from poetry.factory import Factory from poetry.installation.noop_installer import NoopInstaller -from poetry.io.null_io import NullIO from poetry.repositories import Pool from poetry.utils.env import MockEnv from tests.helpers import TestApplication @@ -98,7 +98,6 @@ def poetry(repo, project_directory, config): @pytest.fixture def app(poetry): app_ = TestApplication(poetry) - app_.config.set_terminate_after_run(False) return app_ diff --git a/tests/helpers.py b/tests/helpers.py index 8fc2a381c0f..078e15b6143 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -4,7 +4,7 @@ from pathlib import Path -from poetry.console import Application +from poetry.console.application import Application from poetry.core.masonry.utils.helpers import escape_name from poetry.core.masonry.utils.helpers import escape_version from poetry.core.packages import Dependency diff --git a/tests/inspection/test_info.py b/tests/inspection/test_info.py index ac0c4504e2c..a1edea4a39b 100644 --- a/tests/inspection/test_info.py +++ b/tests/inspection/test_info.py @@ -145,7 +145,8 @@ def test_info_from_setup_cfg(demo_setup_cfg): def test_info_no_setup_pkg_info_no_deps(): info = PackageInfo.from_directory( - FIXTURE_DIR_INSPECTIONS / "demo_no_setup_pkg_info_no_deps", disable_build=True, + FIXTURE_DIR_INSPECTIONS / "demo_no_setup_pkg_info_no_deps", + disable_build=True, ) assert info.name == "demo" assert info.version == "0.1.0" diff --git a/tests/installation/test_authenticator.py b/tests/installation/test_authenticator.py index d19364741d1..5f756c34f91 100644 --- a/tests/installation/test_authenticator.py +++ b/tests/installation/test_authenticator.py @@ -5,14 +5,16 @@ import pytest import requests +from cleo.io.null_io import NullIO + from poetry.installation.authenticator import Authenticator -from poetry.io.null_io import NullIO @pytest.fixture() def mock_remote(http): http.register_uri( - http.GET, re.compile("^https?://foo.bar/(.+?)$"), + http.GET, + re.compile("^https?://foo.bar/(.+?)$"), ) diff --git a/tests/installation/test_chef.py b/tests/installation/test_chef.py index d25f276748d..332d9c4794f 100644 --- a/tests/installation/test_chef.py +++ b/tests/installation/test_chef.py @@ -48,7 +48,9 @@ def test_get_cached_archives_for_link(config, mocker): distributions = Path(__file__).parent.parent.joinpath("fixtures/distributions") mocker.patch.object( - chef, "get_cache_directory_for_link", return_value=distributions, + chef, + "get_cache_directory_for_link", + return_value=distributions, ) archives = chef.get_cached_archives_for_link( diff --git a/tests/installation/test_chooser.py b/tests/installation/test_chooser.py index 75fd52c7926..64d58eab95d 100644 --- a/tests/installation/test_chooser.py +++ b/tests/installation/test_chooser.py @@ -50,7 +50,9 @@ def callback(request, uri, headers): return [200, headers, f.read()] http.register_uri( - http.GET, re.compile("^https://pypi.org/(.+?)/(.+?)/json$"), body=callback, + http.GET, + re.compile("^https://pypi.org/(.+?)/(.+?)/json$"), + body=callback, ) @@ -66,7 +68,9 @@ def callback(request, uri, headers): return [200, headers, f.read()] http.register_uri( - http.GET, re.compile("^https://foo.bar/simple/(.+?)$"), body=callback, + http.GET, + re.compile("^https://foo.bar/simple/(.+?)$"), + body=callback, ) @@ -150,7 +154,11 @@ def test_chooser_chooses_system_specific_wheel_link_if_available( @pytest.mark.parametrize("source_type", ["", "legacy"]) def test_chooser_chooses_sdist_if_no_compatible_wheel_link_is_available( - env, mock_pypi, mock_legacy, source_type, pool, + env, + mock_pypi, + mock_legacy, + source_type, + pool, ): chooser = Chooser(pool, env) @@ -171,7 +179,11 @@ def test_chooser_chooses_sdist_if_no_compatible_wheel_link_is_available( @pytest.mark.parametrize("source_type", ["", "legacy"]) def test_chooser_chooses_distributions_that_match_the_package_hashes( - env, mock_pypi, mock_legacy, source_type, pool, + env, + mock_pypi, + mock_legacy, + source_type, + pool, ): chooser = Chooser(pool, env) diff --git a/tests/installation/test_executor.py b/tests/installation/test_executor.py index ddf6faa2d66..4b1596aeb5e 100644 --- a/tests/installation/test_executor.py +++ b/tests/installation/test_executor.py @@ -8,8 +8,8 @@ import pytest -from clikit.api.formatter.style import Style -from clikit.io.buffered_io import BufferedIO +from cleo.formatters.style import Style +from cleo.io.buffered_io import BufferedIO from poetry.config.config import Config from poetry.core.packages.package import Package @@ -32,10 +32,10 @@ def env(tmp_dir): @pytest.fixture() def io(): io = BufferedIO() - io.formatter.add_style(Style("c1_dark").fg("cyan").dark()) - io.formatter.add_style(Style("c2_dark").fg("default").bold().dark()) - io.formatter.add_style(Style("success_dark").fg("green").dark()) - io.formatter.add_style(Style("warning").fg("yellow")) + io.output.formatter.set_style("c1_dark", Style("cyan", options=["dark"])) + io.output.formatter.set_style("c2_dark", Style("default", options=["bold", "dark"])) + io.output.formatter.set_style("success_dark", Style("green", options=["dark"])) + io.output.formatter.set_style("warning", Style("yellow")) return io @@ -59,7 +59,9 @@ def callback(request, uri, headers): return [200, headers, f.read()] http.register_uri( - http.GET, re.compile("^https://files.pythonhosted.org/.*$"), body=callback, + http.GET, + re.compile("^https://files.pythonhosted.org/.*$"), + body=callback, ) @@ -203,10 +205,10 @@ def test_execute_should_gracefully_handle_io_error(config, mocker, io, env): original_write_line = executor._io.write_line - def write_line(string, flags=None): + def write_line(string, **kwargs): # Simulate UnicodeEncodeError string.encode("ascii") - original_write_line(string, flags) + original_write_line(string, **kwargs) mocker.patch.object(io, "write_line", side_effect=write_line) diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py index 2adcb13cd25..930fcdbf228 100644 --- a/tests/installation/test_installer.py +++ b/tests/installation/test_installer.py @@ -7,7 +7,7 @@ import pytest -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.packages import ProjectPackage from poetry.core.toml.file import TOMLFile @@ -1824,7 +1824,12 @@ def test_installer_can_handle_old_lock_files( pool, config, installed=installed, - executor=Executor(MockEnv(version_info=(2, 7, 18)), pool, config, NullIO(),), + executor=Executor( + MockEnv(version_info=(2, 7, 18)), + pool, + config, + NullIO(), + ), ) installer.use_executor() @@ -1842,7 +1847,10 @@ def test_installer_can_handle_old_lock_files( config, installed=installed, executor=Executor( - MockEnv(version_info=(2, 7, 18), platform="win32"), pool, config, NullIO(), + MockEnv(version_info=(2, 7, 18), platform="win32"), + pool, + config, + NullIO(), ), ) installer.use_executor() diff --git a/tests/installation/test_installer_old.py b/tests/installation/test_installer_old.py index 97c1b163636..21c66e2a176 100644 --- a/tests/installation/test_installer_old.py +++ b/tests/installation/test_installer_old.py @@ -6,7 +6,7 @@ import pytest -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.packages import ProjectPackage from poetry.core.toml.file import TOMLFile diff --git a/tests/installation/test_pip_installer.py b/tests/installation/test_pip_installer.py index 64c64409051..34c9cc6b4bd 100644 --- a/tests/installation/test_pip_installer.py +++ b/tests/installation/test_pip_installer.py @@ -4,9 +4,10 @@ import pytest +from cleo.io.null_io import NullIO + from poetry.core.packages.package import Package from poetry.installation.pip_installer import PipInstaller -from poetry.io.null_io import NullIO from poetry.repositories.legacy_repository import LegacyRepository from poetry.repositories.pool import Pool from poetry.utils.env import NullEnv diff --git a/tests/masonry/builders/fixtures/pep_561_stub_only/pkg-stubs/module.pyi b/tests/masonry/builders/fixtures/pep_561_stub_only/pkg-stubs/module.pyi index d79e6e39ee0..f85a07d465a 100644 --- a/tests/masonry/builders/fixtures/pep_561_stub_only/pkg-stubs/module.pyi +++ b/tests/masonry/builders/fixtures/pep_561_stub_only/pkg-stubs/module.pyi @@ -1,4 +1,5 @@ """Example module""" from typing import Tuple + version_info = Tuple[int, int, int] diff --git a/tests/masonry/builders/fixtures/pep_561_stub_only_partial/pkg-stubs/module.pyi b/tests/masonry/builders/fixtures/pep_561_stub_only_partial/pkg-stubs/module.pyi index d79e6e39ee0..f85a07d465a 100644 --- a/tests/masonry/builders/fixtures/pep_561_stub_only_partial/pkg-stubs/module.pyi +++ b/tests/masonry/builders/fixtures/pep_561_stub_only_partial/pkg-stubs/module.pyi @@ -1,4 +1,5 @@ """Example module""" from typing import Tuple + version_info = Tuple[int, int, int] diff --git a/tests/masonry/builders/fixtures/pep_561_stub_only_src/src/pkg-stubs/module.pyi b/tests/masonry/builders/fixtures/pep_561_stub_only_src/src/pkg-stubs/module.pyi index d79e6e39ee0..f85a07d465a 100644 --- a/tests/masonry/builders/fixtures/pep_561_stub_only_src/src/pkg-stubs/module.pyi +++ b/tests/masonry/builders/fixtures/pep_561_stub_only_src/src/pkg-stubs/module.pyi @@ -1,4 +1,5 @@ """Example module""" from typing import Tuple + version_info = Tuple[int, int, int] diff --git a/tests/masonry/builders/test_editable_builder.py b/tests/masonry/builders/test_editable_builder.py index 5500bc49a4d..8e236b9b188 100644 --- a/tests/masonry/builders/test_editable_builder.py +++ b/tests/masonry/builders/test_editable_builder.py @@ -8,8 +8,9 @@ import pytest +from cleo.io.null_io import NullIO + from poetry.factory import Factory -from poetry.io.null_io import NullIO from poetry.masonry.builders.editable import EditableBuilder from poetry.utils.env import EnvManager from poetry.utils.env import MockEnv @@ -78,10 +79,11 @@ def test_builder_installs_proper_files_for_standard_packages(simple_poetry, tmp_ assert tmp_venv._bin_dir.joinpath("foo").exists() assert tmp_venv.site_packages.path.joinpath("simple_project.pth").exists() - assert simple_poetry.file.parent.resolve().as_posix() == tmp_venv.site_packages.path.joinpath( - "simple_project.pth" - ).read_text().strip( - os.linesep + assert ( + simple_poetry.file.parent.resolve().as_posix() + == tmp_venv.site_packages.path.joinpath("simple_project.pth") + .read_text() + .strip(os.linesep) ) dist_info = tmp_venv.site_packages.path.joinpath("simple_project-1.2.3.dist-info") diff --git a/tests/mixology/solutions/solutions/test_python_requirement_solution.py b/tests/mixology/solutions/solutions/test_python_requirement_solution.py index 8ea58a4078d..46646b5ec81 100644 --- a/tests/mixology/solutions/solutions/test_python_requirement_solution.py +++ b/tests/mixology/solutions/solutions/test_python_requirement_solution.py @@ -1,4 +1,4 @@ -from clikit.io.buffered_io import BufferedIO +from cleo.io.buffered_io import BufferedIO from poetry.core.packages.dependency import Dependency from poetry.mixology.failure import SolveFailure diff --git a/tests/mixology/version_solver/conftest.py b/tests/mixology/version_solver/conftest.py index b31634b85db..ad0dacfbe75 100644 --- a/tests/mixology/version_solver/conftest.py +++ b/tests/mixology/version_solver/conftest.py @@ -1,6 +1,6 @@ import pytest -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.packages.project_package import ProjectPackage from poetry.puzzle.provider import Provider as BaseProvider diff --git a/tests/publishing/test_publisher.py b/tests/publishing/test_publisher.py index 786d659b0db..d35dcf8f2ca 100644 --- a/tests/publishing/test_publisher.py +++ b/tests/publishing/test_publisher.py @@ -4,10 +4,10 @@ import pytest -from cleo.io import BufferedIO +from cleo.io.buffered_io import BufferedIO +from cleo.io.null_io import NullIO from poetry.factory import Factory -from poetry.io.null_io import NullIO from poetry.publishing.publisher import Publisher diff --git a/tests/publishing/test_uploader.py b/tests/publishing/test_uploader.py index ae0eb041b7b..8f5ec1b9e7a 100644 --- a/tests/publishing/test_uploader.py +++ b/tests/publishing/test_uploader.py @@ -2,8 +2,9 @@ import pytest +from cleo.io.null_io import NullIO + from poetry.factory import Factory -from poetry.io.null_io import NullIO from poetry.publishing.uploader import Uploader from poetry.publishing.uploader import UploadError diff --git a/tests/puzzle/test_provider.py b/tests/puzzle/test_provider.py index 2d0c4557bdb..d7ab8f8788a 100644 --- a/tests/puzzle/test_provider.py +++ b/tests/puzzle/test_provider.py @@ -3,7 +3,7 @@ import pytest -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.packages import ProjectPackage from poetry.core.packages.directory_dependency import DirectoryDependency diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py index 6e2a53a5c22..75b5c565ed5 100644 --- a/tests/puzzle/test_solver.py +++ b/tests/puzzle/test_solver.py @@ -2,7 +2,7 @@ import pytest -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.packages import Package from poetry.core.packages import ProjectPackage @@ -499,7 +499,8 @@ def test_solver_returns_extras_only_requested(solver, repo, package, enabled_ext ) check_solver_result( - ops, expected, + ops, + expected, ) assert ops[-1].package.marker.is_any() @@ -544,7 +545,8 @@ def test_solver_returns_extras_when_multiple_extras_use_same_dependency( expected.insert(0, {"job": "install", "package": package_c}) check_solver_result( - ops, expected, + ops, + expected, ) assert ops[-1].package.marker.is_any() @@ -2353,7 +2355,8 @@ def test_ignore_python_constraint_no_overlap_dependencies(solver, repo, package) ops = solver.solve() check_solver_result( - ops, [{"job": "install", "package": pytest}], + ops, + [{"job": "install", "package": pytest}], ) @@ -2570,7 +2573,8 @@ def test_solver_should_use_the_python_constraint_from_the_environment_if_availab ops = solver.solve() check_solver_result( - ops, [{"job": "install", "package": b}, {"job": "install", "package": a}], + ops, + [{"job": "install", "package": b}, {"job": "install", "package": a}], ) diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py index f0e2bd21a45..da810307a9f 100644 --- a/tests/utils/test_env.py +++ b/tests/utils/test_env.py @@ -9,7 +9,7 @@ import pytest import tomlkit -from clikit.io import NullIO +from cleo.io.null_io import NullIO from poetry.core.semver import Version from poetry.core.toml.file import TOMLFile @@ -144,7 +144,8 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( "subprocess.Popen.communicate", @@ -184,10 +185,12 @@ def test_activate_activates_existing_virtualenv_no_envs_file( config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( - "subprocess.Popen.communicate", side_effect=[("/prefix", None)], + "subprocess.Popen.communicate", + side_effect=[("/prefix", None)], ) m = mocker.patch("poetry.utils.env.EnvManager.build_venv", side_effect=build_venv) @@ -223,10 +226,12 @@ def test_activate_activates_same_virtualenv_with_envs_file( config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( - "subprocess.Popen.communicate", side_effect=[("/prefix", None)], + "subprocess.Popen.communicate", + side_effect=[("/prefix", None)], ) m = mocker.patch("poetry.utils.env.EnvManager.create_venv") @@ -303,7 +308,8 @@ def test_activate_activates_recreates_for_different_patch( config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( "subprocess.Popen.communicate", @@ -404,7 +410,8 @@ def test_deactivate_non_activated_but_existing( config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) manager.deactivate(NullIO()) @@ -442,7 +449,8 @@ def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker): config.merge({"virtualenvs": {"path": str(tmp_dir)}}) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) manager.deactivate(NullIO()) @@ -473,10 +481,12 @@ def test_get_prefers_explicitly_activated_virtualenvs_over_env_var( envs_file.write(doc) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( - "subprocess.Popen.communicate", side_effect=[("/prefix", None)], + "subprocess.Popen.communicate", + side_effect=[("/prefix", None)], ) env = manager.get() @@ -814,7 +824,8 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( ) mocker.patch( - "subprocess.check_output", side_effect=check_output_wrapper(), + "subprocess.check_output", + side_effect=check_output_wrapper(), ) mocker.patch( "subprocess.Popen.communicate", @@ -846,7 +857,8 @@ def test_system_env_has_correct_paths(): @pytest.mark.parametrize( - ("enabled",), [(True,), (False,)], + ("enabled",), + [(True,), (False,)], ) def test_system_env_usersite(mocker, enabled): mocker.patch("site.check_enableusersite", return_value=enabled) diff --git a/tests/utils/test_exporter.py b/tests/utils/test_exporter.py index f15e2dc53a3..5fed10d1c99 100644 --- a/tests/utils/test_exporter.py +++ b/tests/utils/test_exporter.py @@ -974,7 +974,10 @@ def test_exporter_can_export_requirements_txt_with_file_packages_and_markers( def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry): poetry.pool.add_repository( - LegacyRepository("custom", "https://example.com/simple",) + LegacyRepository( + "custom", + "https://example.com/simple", + ) ) poetry.locker.mock_lock_data( { @@ -1030,7 +1033,12 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry) def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host( tmp_dir, poetry ): - poetry.pool.add_repository(LegacyRepository("custom", "http://example.com/simple",)) + poetry.pool.add_repository( + LegacyRepository( + "custom", + "http://example.com/simple", + ) + ) poetry.locker.mock_lock_data( { "package": [ @@ -1139,9 +1147,17 @@ def test_exporter_exports_requirements_txt_with_legacy_packages_and_duplicate_so tmp_dir, poetry ): poetry.pool.add_repository( - LegacyRepository("custom", "https://example.com/simple",) + LegacyRepository( + "custom", + "https://example.com/simple", + ) + ) + poetry.pool.add_repository( + LegacyRepository( + "custom", + "https://foobaz.com/simple", + ) ) - poetry.pool.add_repository(LegacyRepository("custom", "https://foobaz.com/simple",)) poetry.locker.mock_lock_data( { "package": [