Commit 855bc88b by Sébastien Eustace Committed by GitHub

Merge pull request #3618 from python-poetry/new-cleo

Migrate to the new version of Cleo
parents a104970f a8d02ef5
[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__
......
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
......@@ -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"
......@@ -327,14 +315,6 @@ 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"
description = "Pexpect allows easy control of interactive console applications."
......@@ -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"},
......
......@@ -2,6 +2,6 @@ import sys
if __name__ == "__main__":
from .console import main
from .console.application import main
sys.exit(main())
from .application import Application
def main(): # type: () -> int
return Application().run()
import sys
import logging
import re
from importlib import import_module
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Optional
from typing import cast
from cleo import Application as BaseApplication
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",
]
if TYPE_CHECKING:
......@@ -36,36 +79,24 @@ if TYPE_CHECKING:
class Application(BaseApplication):
def __init__(self): # type: () -> None
super(Application, self).__init__(
"poetry", __version__, config=ApplicationConfig("poetry", __version__)
)
def __init__(self) -> None:
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 = "<c1>{}</c1>".format(
".".join(str(v) for v in sys.version_info[:2])
)
poetry_feature_release = "<c1>1.2</c1>"
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 <c1>env</c1> command.\n"
"See <fg=blue>https://python-poetry.org/docs/managing-environments/</> "
"for more information."
).format(python_version, poetry_feature_release, python_version)
self._preliminary_io.error_line("<fg=yellow>{}</>\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): # type: () -> "Poetry"
def poetry(self) -> "Poetry":
from pathlib import Path
from poetry.factory import Factory
......@@ -77,45 +108,173 @@ class Application(BaseApplication):
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: <comment>{}</>".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()
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
......@@ -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
......
from cleo import option
from cleo.helpers import option
from .env_command import EnvCommand
......
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): # type: () -> int
return self.call("help", self._config.name)
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.")]
......
......@@ -7,7 +7,7 @@ from ..command import Command
class CacheListCommand(Command):
name = "list"
name = "cache list"
description = "List Poetry's caches."
def handle(self): # type: () -> Optional[int]
......
from typing import TYPE_CHECKING
from cleo import Command as BaseCommand
from cleo.commands.command import Command as BaseCommand
if TYPE_CHECKING:
......
......@@ -8,8 +8,8 @@ from typing import List
from typing import Optional
from typing import Tuple
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
......@@ -81,7 +81,11 @@ To remove a repository (repo is a short alias for repositories):
boolean_normalizer,
False,
),
"installer.parallel": (boolean_validator, boolean_normalizer, True,),
"installer.parallel": (
boolean_validator,
boolean_normalizer,
True,
),
}
return unique_config_values
......
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()]
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): # type: () -> int
......@@ -25,7 +23,6 @@ class DebugInfoCommand(Command):
]
)
)
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)
from typing import Optional
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 = [
......@@ -30,9 +31,10 @@ class DebugResolveCommand(InitCommand):
loggers = ["poetry.repositories.pypi_repository", "poetry.inspection.info"]
def handle(self): # type: () -> Optional[int]
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
......@@ -51,14 +53,12 @@ class DebugResolveCommand(InitCommand):
)
# 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")
......@@ -103,7 +103,8 @@ class DebugResolveCommand(InitCommand):
return 0
table = self.table([], style="borderless")
table = self.table([], style="compact")
table.style.set_vertical_border_chars("", " ")
rows = []
if self.option("install"):
......@@ -136,4 +137,4 @@ class DebugResolveCommand(InitCommand):
rows.append(row)
table.set_rows(rows)
table.render(self.io)
table.render()
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)
from typing import TYPE_CHECKING
from typing import Optional
from cleo import option
from cleo.helpers import option
from ..command import Command
......@@ -12,7 +12,7 @@ if TYPE_CHECKING:
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.")]
......
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.")]
......
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 = [
......
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.")]
......
from cleo import option
from cleo.helpers import option
from poetry.utils.exporter import Exporter
......@@ -50,7 +50,7 @@ class ExportCommand(Command):
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(
......
......@@ -13,7 +13,7 @@ from typing import Optional
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
......
from cleo import option
from cleo.helpers import option
from .installer_command import InstallerCommand
......@@ -21,7 +21,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",
......@@ -87,7 +89,7 @@ dependencies and not including the current project, run the command with the
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(
"<b>Installing</> the current project: <c1>{}</c1> (<c2>{}</c2>)".format(
self.poetry.package.pretty_name, self.poetry.package.pretty_version
......@@ -106,7 +108,7 @@ dependencies and not including the current project, run the command with the
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(
"<b>Installing</> the current project: <c1>{}</c1> (<success>{}</success>)".format(
self.poetry.package.pretty_name, self.poetry.package.pretty_version
......
from cleo import option
from cleo.helpers import option
from .installer_command import InstallerCommand
......
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
......
from pathlib import Path
from typing import Optional
from cleo import option
from cleo.helpers import option
from .command import Command
......
from cleo import argument
from cleo import option
from cleo.helpers import argument
from cleo.helpers import option
from .installer_command import InstallerCommand
......
from typing import Any
from typing import Union
from cleo import argument
from cleo.helpers import argument
from .env_command import EnvCommand
......@@ -15,13 +15,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): # type: () -> Any
args = self.argument("args")
script = args[0]
......@@ -32,6 +25,17 @@ class RunCommand(EnvCommand):
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): # type: (Union[str, dict], str) -> Any
if isinstance(script, dict):
script = script["callable"]
......
from cleo import argument
from cleo.helpers import argument
from .command import Command
......
from ..command import Command
from .update import SelfUpdateCommand
class SelfCommand(Command):
name = "self"
description = "Interact with Poetry directly."
commands = [SelfUpdateCommand()]
def handle(self): # type: () -> int
return self.call("help", self._config.name)
......@@ -14,9 +14,10 @@ from gzip import GzipFile
from typing import TYPE_CHECKING
from typing import Any
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
......@@ -59,7 +60,7 @@ BAT = '@echo off\r\n{python_executable} "{poetry_bin}" %*\r\n'
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)]
......@@ -253,9 +254,9 @@ class SelfUpdateCommand(Command):
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): # type: ("Version") -> str
......
......@@ -4,8 +4,8 @@ from typing import List
from typing import Optional
from typing import Union
from cleo import argument
from cleo import option
from cleo.helpers import argument
from cleo.helpers import option
from .env_command import EnvCommand
......@@ -47,9 +47,9 @@ lists all packages available."""
colors = ["cyan", "yellow", "green", "magenta", "blue"]
def handle(self): # type: () -> Optional[int]
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
......@@ -62,7 +62,7 @@ lists all packages available."""
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)
......@@ -82,7 +82,6 @@ lists all packages available."""
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)
......@@ -155,7 +154,7 @@ lists all packages available."""
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":
......@@ -218,7 +217,7 @@ lists all packages available."""
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 = " (!)"
......@@ -362,7 +361,7 @@ lists all packages available."""
)
def _write_tree_line(self, io, line): # type: ("IO", str) -> None
if not io.output.supports_ansi():
if not io.output.supports_utf8():
line = line.replace("└", "`-")
line = line.replace("├", "|-")
line = line.replace("──", "-")
......@@ -371,17 +370,17 @@ lists all packages available."""
io.write_line(line)
def init_styles(self, io): # type: ("IO") -> None
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
): # type: ("Package", bool) -> Union["Package", bool]
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
......
from cleo import argument
from cleo import option
from cleo.helpers import argument
from cleo.helpers import option
from .installer_command import InstallerCommand
......
from cleo import argument
from cleo import option
from cleo.helpers import argument
from cleo.helpers import option
from .command import Command
......
from .application_config import ApplicationConfig
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): # type: () -> None
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: <comment>{}</>".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
from cleo.exceptions import CleoSimpleException
class PoetrySimpleConsoleException(CleoSimpleException):
pass
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
......@@ -5,14 +5,14 @@ from pathlib import Path
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
......
......@@ -17,7 +17,7 @@ if TYPE_CHECKING:
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
......
......@@ -14,10 +14,11 @@ from typing import Any
from typing import List
from typing import Union
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
......@@ -91,7 +92,7 @@ class Executor(object):
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): # type: () -> "Executor"
self._enabled = False
......@@ -176,7 +177,7 @@ class Executor(object):
with self._lock:
section = self._sections[id(operation)]
section.output.clear()
section.clear()
section.write(line)
def _execute_operation(self, operation): # type: ("OperationTypes") -> None
......@@ -225,13 +226,15 @@ class Executor(object):
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 = " <error>•</error> {message}: <error>Failed</error>".format(
message=self.get_operation_message(operation, error=True),
message = (
" <error>•</error> {message}: <error>Failed</error>".format(
message=self.get_operation_message(operation, error=True),
)
)
self._write(operation, message)
io = self._sections.get(id(operation), self._io)
......@@ -268,7 +271,8 @@ class Executor(object):
"<fg=default;options=bold,dark>Skipped</> "
"<fg=default;options=dark>for the following reason:</> "
"<fg=default;options=bold,dark>{reason}</>".format(
message=operation_message, reason=operation.skip_reason,
message=operation_message,
reason=operation.skip_reason,
),
)
......@@ -430,8 +434,10 @@ class Executor(object):
return self._update(operation)
def _execute_uninstall(self, operation): # type: (Uninstall) -> int
message = " <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format(
message=self.get_operation_message(operation),
message = (
" <fg=blue;options=bold>•</> {message}: <info>Removing...</info>".format(
message=self.get_operation_message(operation),
)
)
self._write(operation, message)
......@@ -453,8 +459,10 @@ class Executor(object):
archive = self._download(operation)
operation_message = self.get_operation_message(operation)
message = " <fg=blue;options=bold>•</> {message}: <info>Installing...</info>".format(
message=operation_message,
message = (
" <fg=blue;options=bold>•</> {message}: <info>Installing...</info>".format(
message=operation_message,
)
)
self._write(operation, message)
......@@ -487,8 +495,10 @@ class Executor(object):
def _prepare_file(self, operation): # type: (Union[Install, Update]) -> Path
package = operation.package
message = " <fg=blue;options=bold>•</> {message}: <info>Preparing...</info>".format(
message=self.get_operation_message(operation),
message = (
" <fg=blue;options=bold>•</> {message}: <info>Preparing...</info>".format(
message=self.get_operation_message(operation),
)
)
self._write(operation, message)
......@@ -506,8 +516,10 @@ class Executor(object):
package = operation.package
operation_message = self.get_operation_message(operation)
message = " <fg=blue;options=bold>•</> {message}: <info>Building...</info>".format(
message=operation_message,
message = (
" <fg=blue;options=bold>•</> {message}: <info>Building...</info>".format(
message=operation_message,
)
)
self._write(operation, message)
......@@ -570,8 +582,10 @@ class Executor(object):
package = operation.package
operation_message = self.get_operation_message(operation)
message = " <fg=blue;options=bold>•</> {message}: <info>Cloning...</info>".format(
message=operation_message,
message = (
" <fg=blue;options=bold>•</> {message}: <info>Cloning...</info>".format(
message=operation_message,
)
)
self._write(operation, message)
......@@ -637,18 +651,20 @@ class Executor(object):
)
wheel_size = response.headers.get("content-length")
operation_message = self.get_operation_message(operation)
message = " <fg=blue;options=bold>•</> {message}: <info>Downloading...</>".format(
message=operation_message,
message = (
" <fg=blue;options=bold>•</> {message}: <info>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)], max=int(wheel_size)
)
progress.set_format(message + " <b>%percent%%</b>")
......
......@@ -4,11 +4,11 @@ from typing import List
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
......
......@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
from typing import Any
from typing import Union
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
......@@ -184,8 +184,9 @@ class PipInstaller(BaseInstaller):
return name
def install_directory(self, package): # type: ("Package") -> Union[str, int]
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()
......
from typing import Any
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): # type: (*Any, **Any) -> None
super(NullIO, self).__init__(*args, **kwargs)
......@@ -351,7 +351,9 @@ class Locker(object):
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 (),
)
)
......
......@@ -239,6 +239,8 @@ class Uploader:
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(
{
......@@ -255,7 +257,7 @@ class Uploader:
("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 <c1>{0}</c1> <b>%percent%%</b>".format(file.name)
)
......@@ -283,7 +285,7 @@ class Uploader:
)
bar.finish()
elif resp.status_code == 301:
if self._io.output.supports_ansi():
if self._io.output.is_decorated():
self._io.overwrite(
" - Uploading <c1>{0}</c1> <error>{1}</>".format(
file.name, "FAILED"
......@@ -294,7 +296,7 @@ class Uploader:
"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 <c1>{0}</c1> <error>{1}</>".format(
file.name, "FAILED"
......
import logging
import os
import re
import time
import urllib.parse
from contextlib import contextmanager
......@@ -13,7 +14,7 @@ from typing import List
from typing import Optional
from typing import Union
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
......@@ -45,7 +46,10 @@ logger = logging.getLogger(__name__)
class Indicator(ProgressIndicator):
pass
def _formatter_elapsed(self):
elapsed = time.time() - self._start_time
return "{:.1f}s".format(elapsed)
class Provider:
......@@ -663,8 +667,10 @@ class Provider:
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
......@@ -777,7 +783,7 @@ class Provider:
@contextmanager
def progress(self): # type: () -> Iterator[None]
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:
......
......@@ -11,7 +11,7 @@ from typing import Optional
from typing import Tuple
from typing import Union
from clikit.api.io import IO
from cleo.io.io import IO
from poetry.core.packages import Package
from poetry.core.packages.project_package import ProjectPackage
......@@ -201,7 +201,12 @@ class Solver:
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(
......
......@@ -44,7 +44,8 @@ class InstalledRepository(Repository):
# 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 @@ class InstalledRepository(Repository):
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))
......
......@@ -25,7 +25,7 @@ import packaging.tags
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
......
......@@ -5,7 +5,7 @@ from typing import Optional
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
......
......@@ -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]
......
......@@ -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()
......@@ -11,7 +11,7 @@ from typing import Dict
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_mock(mocker):
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 command_tester_factory(app, env):
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
......
......@@ -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 @@ Resolving dependencies...
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 @@ Resolving dependencies...
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 @@ Resolving dependencies...
Resolution results:
pendulum 2.0.3
demo 0.1.2
pendulum 2.0.3
demo 0.1.2
"""
assert expected == tester.io.fetch_output()
......@@ -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()
......@@ -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(
......
......@@ -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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 4 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 4 installs, 0 updates, 0 removals
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
)
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 @@ Package operations: 2 installs, 0 updates, 0 removals
)
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 @@ Package operations: 2 installs, 0 updates, 0 removals
)
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 @@ Package operations: 2 installs, 0 updates, 0 removals
)
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 2 installs, 0 updates, 0 removals
"""
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 @@ Package operations: 4 installs, 0 updates, 0 removals
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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 @@ Package operations: 1 install, 0 updates, 0 removals
"""
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"]
......
......@@ -6,7 +6,7 @@ from pathlib import Path
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 @@ python = "~2.7 || ^3.6"
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
......
......@@ -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 test_publish_returns_non_zero_code_for_connection_errors(app, app_tester, ht
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):
......
......@@ -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
......@@ -21,7 +21,8 @@ def tester(command_tester_factory):
def test_search(
tester, http,
tester,
http,
):
tester.execute("sqlalchemy")
......
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()
import pytest
from poetry.console.commands import VersionCommand
from poetry.console.commands.version import VersionCommand
@pytest.fixture()
......
......@@ -4,11 +4,11 @@ from pathlib import Path
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_
......
......@@ -4,7 +4,7 @@ import urllib.parse
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
......
......@@ -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"
......
......@@ -5,14 +5,16 @@ import httpretty
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/(.+?)$"),
)
......
......@@ -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(
......
......@@ -50,7 +50,9 @@ def mock_pypi(http):
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 mock_legacy(http):
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)
......
......@@ -8,8 +8,8 @@ from pathlib import Path
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 mock_file_downloads(http):
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)
......
......@@ -7,7 +7,7 @@ from pathlib import Path
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
......@@ -1854,7 +1854,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()
......@@ -1872,7 +1877,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()
......
......@@ -6,7 +6,7 @@ from pathlib import Path
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
......
......@@ -4,9 +4,10 @@ from pathlib import Path
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
......
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
"""Example module"""
from typing import Tuple
version_info = Tuple[int, int, int]
......@@ -8,8 +8,9 @@ from pathlib import Path
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")
......
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
......
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
......
......@@ -4,10 +4,10 @@ from pathlib import Path
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
......
......@@ -2,8 +2,9 @@ from pathlib import Path
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
......
......@@ -3,7 +3,7 @@ from subprocess import CalledProcessError
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
......
......@@ -2,7 +2,7 @@ from pathlib import Path
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}],
)
......
......@@ -9,7 +9,7 @@ from typing import Union
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)
......
......@@ -974,7 +974,10 @@ foo @ {}/tests/fixtures/distributions/demo-0.1.0.tar.gz; python_version < "3.7"
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 @@ foo==1.2.3 \\
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": [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment