Commit 2ff796ed by Sébastien Eustace Committed by GitHub

Upgrade to latest version of Cleo (#722)

* Upgrade Cleo to the new improved version

* Update sonnet script to use sub commands
parent a51d6642
import os import os
import re
import sys
import traceback
from cleo import Application as BaseApplication from cleo import Application as BaseApplication
from cleo.formatters import Formatter
from cleo.inputs import ArgvInput
from cleo.outputs import ConsoleOutput
from cleo.outputs import Output
from poetry import __version__ from poetry import __version__
from poetry.io.raw_argv_input import RawArgvInput
from .commands import AboutCommand from .commands import AboutCommand
from .commands import AddCommand from .commands import AddCommand
from .commands import BuildCommand from .commands import BuildCommand
...@@ -34,22 +25,25 @@ from .commands import ShowCommand ...@@ -34,22 +25,25 @@ from .commands import ShowCommand
from .commands import UpdateCommand from .commands import UpdateCommand
from .commands import VersionCommand from .commands import VersionCommand
from .commands.cache import CacheClearCommand from .commands.debug import DebugCommand
from .commands.cache import CacheCommand
from .commands.debug import DebugInfoCommand from .commands.self import SelfCommand
from .commands.debug import DebugResolveCommand
from .commands.self import SelfUpdateCommand from .config import ApplicationConfig
class Application(BaseApplication): class Application(BaseApplication):
def __init__(self): def __init__(self):
super(Application, self).__init__("Poetry", __version__) super(Application, self).__init__(
"poetry", __version__, config=ApplicationConfig("poetry", __version__)
)
self._poetry = None self._poetry = None
self._skip_io_configuration = False
self._formatter = Formatter(True) for command in self.get_default_commands():
self._formatter.add_style("error", "red", options=["bold"]) self.add(command)
@property @property
def poetry(self): def poetry(self):
...@@ -65,47 +59,8 @@ class Application(BaseApplication): ...@@ -65,47 +59,8 @@ class Application(BaseApplication):
def reset_poetry(self): # type: () -> None def reset_poetry(self): # type: () -> None
self._poetry = None self._poetry = None
def run(self, i=None, o=None): # type: (...) -> int
if i is None:
i = ArgvInput()
if o is None:
o = ConsoleOutput()
self._formatter.with_colors(o.is_decorated())
o.set_formatter(self._formatter)
name = i.get_first_argument()
if name in ["run", "script"]:
self._skip_io_configuration = True
i = RawArgvInput()
return super(Application, self).run(i, o)
def do_run(self, i, o):
name = self.get_command_name(i)
if name not in ["run", "script"]:
return super(Application, self).do_run(i, o)
command = self.find(name)
self._running_command = command
status_code = command.run(i, o)
self._running_command = None
return status_code
def configure_io(self, i, o):
if self._skip_io_configuration:
return
super(Application, self).configure_io(i, o)
def get_default_commands(self): # type: () -> list def get_default_commands(self): # type: () -> list
commands = super(Application, self).get_default_commands() commands = [
commands += [
AboutCommand(), AboutCommand(),
AddCommand(), AddCommand(),
BuildCommand(), BuildCommand(),
...@@ -129,74 +84,16 @@ class Application(BaseApplication): ...@@ -129,74 +84,16 @@ class Application(BaseApplication):
] ]
# Cache commands # Cache commands
commands += [CacheClearCommand()] commands += [CacheCommand()]
# Debug commands # Debug command
commands += [DebugInfoCommand(), DebugResolveCommand()] commands += [DebugCommand()]
# Self commands # Self commands
commands += [SelfUpdateCommand()] commands += [SelfCommand()]
return commands return commands
def render_exception(self, e, o):
tb = traceback.extract_tb(sys.exc_info()[2])
title = "[<error>%s</error>] " % e.__class__.__name__
l = len(title)
width = self._terminal.width
if not width:
width = sys.maxsize
formatter = o.get_formatter()
lines = []
for line in re.split(r"\r?\n", str(e)):
for splitline in [
line[x : x + (width - 4)] for x in range(0, len(line), width - 4)
]:
line_length = (
len(re.sub(r"\[[^m]*m", "", formatter.format(splitline))) + 4
)
lines.append((splitline, line_length))
l = max(line_length, l)
messages = []
empty_line = formatter.format("%s" % (" " * l))
messages.append(empty_line)
messages.append(
formatter.format("%s%s" % (title, " " * max(0, l - len(title))))
)
for line in lines:
messages.append(
formatter.format(
"<error>%s %s</error>" % (line[0], " " * (l - line[1]))
)
)
messages.append(empty_line)
o.writeln(messages, Output.OUTPUT_RAW)
if Output.VERBOSITY_VERBOSE <= o.get_verbosity():
o.writeln("<comment>Exception trace:</comment>")
for exc_info in tb:
file_ = exc_info[0]
line_number = exc_info[1]
function = exc_info[2]
line = exc_info[3]
o.writeln(
" <info>%s</info> in <fg=cyan>%s()</> "
"at line <info>%s</info>" % (file_, function, line_number)
)
o.writeln(" %s" % line)
o.writeln("")
if self._running_command is not None:
o.writeln("<info>%s</info>" % self._running_command.get_synopsis())
o.writeln("") if __name__ == "__main__":
Application().run()
from clikit.api.args import Args
from clikit.api.args import RawArgs
from clikit.api.args.format import ArgsFormat
from clikit.api.args.format import ArgsFormatBuilder
from clikit.args import DefaultArgsParser
class RunArgsParser(DefaultArgsParser):
"""
Parser that just parses command names and leave the rest
alone to be passed to the command.
"""
def parse(
self, args, fmt, lenient=False
): # type: (RawArgs, ArgsFormat, bool) -> Args
builder = ArgsFormatBuilder()
builder.set_command_names(*fmt.get_command_names())
builder.set_arguments(*fmt.get_arguments().values())
fmt = builder.format
return super(RunArgsParser, self).parse(args, fmt, True)
def _parse(
self, raw_args, fmt, lenient
): # type: (RawArgs, ArgsFormat, bool) -> None
"""
Parse everything as a single, multi-valued argument.
"""
tokens = raw_args.tokens[:]
last_arg = list(fmt.get_arguments().values())[-1]
self._arguments[last_arg.name] = []
while True:
try:
token = tokens.pop(0)
except IndexError:
break
self._arguments[last_arg.name].append(token)
...@@ -25,7 +25,7 @@ class AddCommand(EnvCommand, InitCommand): ...@@ -25,7 +25,7 @@ class AddCommand(EnvCommand, InitCommand):
If you do not specify a version constraint, poetry will choose a suitable one based on the available package versions. If you do not specify a version constraint, poetry will choose a suitable one based on the available package versions.
""" """
_loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self):
from poetry.installation import Installer from poetry.installation import Installer
...@@ -124,11 +124,7 @@ If you do not specify a version constraint, poetry will choose a suitable one ba ...@@ -124,11 +124,7 @@ If you do not specify a version constraint, poetry will choose a suitable one ba
self.reset_poetry() self.reset_poetry()
installer = Installer( installer = Installer(
self.output, self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
) )
installer.dry_run(self.option("dry-run")) installer.dry_run(self.option("dry-run"))
......
...@@ -23,5 +23,5 @@ class BuildCommand(EnvCommand): ...@@ -23,5 +23,5 @@ class BuildCommand(EnvCommand):
) )
) )
builder = Builder(self.poetry, self.env, self.output) builder = Builder(self.poetry, self.env, self.io)
builder.build(fmt) builder.build(fmt)
from .clear import CacheClearCommand from .cache import CacheCommand
from ..command import Command
from .clear import CacheClearCommand
class CacheCommand(Command):
"""
Interact with Poetry's cache.
cache
"""
commands = [CacheClearCommand()]
def handle(self):
return self.call("help", self._config.name)
...@@ -7,7 +7,7 @@ class CacheClearCommand(Command): ...@@ -7,7 +7,7 @@ class CacheClearCommand(Command):
""" """
Clears poetry's cache. Clears poetry's cache.
cache:clear clear
{ cache : The name of the cache to clear. } { cache : The name of the cache to clear. }
{ --all : Clear all caches. } { --all : Clear all caches. }
""" """
......
...@@ -17,7 +17,7 @@ class CheckCommand(Command): ...@@ -17,7 +17,7 @@ class CheckCommand(Command):
return 0 return 0
for error in check_result["errors"]: for error in check_result["errors"]:
self.error("Error: {}".format(error)) self.line("<error>Error: {}</error>".format(error))
for error in check_result["warnings"]: for error in check_result["warnings"]:
self.line("<warning>Warning: {}</warning>".format(error)) self.line("<warning>Warning: {}</warning>".format(error))
......
import logging
from cleo import Command as BaseCommand from cleo import Command as BaseCommand
from ..styles.poetry import PoetryStyle
class CommandFormatter(logging.Formatter):
_colors = {
"error": "fg=red",
"warning": "fg=yellow",
"debug": "debug",
"info": "fg=blue",
}
def format(self, record):
if not record.exc_info:
level = record.levelname.lower()
msg = record.msg
if level in self._colors:
msg = "<{}>{}</>".format(self._colors[level], msg)
return msg
return super(CommandFormatter, self).format(record)
class CommandHandler(logging.Handler):
def __init__(self, command):
self._command = command
output = self._command.output
level = logging.WARNING
if output.is_debug():
level = logging.DEBUG
elif output.is_very_verbose() or output.is_verbose():
level = logging.INFO
super(CommandHandler, self).__init__(level)
def emit(self, record):
try:
msg = self.format(record)
level = record.levelname.lower()
err = level in ("warning", "error", "exception", "critical")
if err:
self._command.output.write_error(msg, newline=True)
else:
self._command.line(msg)
except Exception:
self.handleError(record)
class Command(BaseCommand): class Command(BaseCommand):
_loggers = [] loggers = []
@property @property
def poetry(self): def poetry(self):
return self.get_application().poetry return self.application.poetry
def reset_poetry(self): # type: () -> None def reset_poetry(self): # type: () -> None
self.get_application().reset_poetry() self.application.reset_poetry()
def run(self, i, o): # type: () -> int
"""
Initialize command.
"""
self.input = i
self.output = PoetryStyle(i, o)
for logger in self._loggers:
self.register_logger(logging.getLogger(logger))
return super(BaseCommand, self).run(i, o)
def register_logger(self, logger):
"""
Register a new logger.
"""
handler = CommandHandler(self)
handler.setFormatter(CommandFormatter())
logger.handlers = [handler]
logger.propagate = False
output = self.output
level = logging.WARNING
if output.is_debug():
level = logging.DEBUG
elif output.is_very_verbose() or output.is_verbose():
level = logging.INFO
logger.setLevel(level)
...@@ -18,7 +18,7 @@ class ConfigCommand(Command): ...@@ -18,7 +18,7 @@ class ConfigCommand(Command):
Sets/Gets config options. Sets/Gets config options.
config config
{ key : Setting key. } { key? : Setting key. }
{ value?* : Setting value. } { value?* : Setting value. }
{ --list : List configuration settings } { --list : List configuration settings }
{ --unset : Unset configuration setting } { --unset : Unset configuration setting }
...@@ -40,7 +40,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -40,7 +40,7 @@ To remove a repository (repo is a short alias for repositories):
super(ConfigCommand, self).__init__() super(ConfigCommand, self).__init__()
self._config = Config.create("config.toml") self._settings_config = Config.create("config.toml")
self._auth_config = Config.create("auth.toml") self._auth_config = Config.create("auth.toml")
@property @property
...@@ -74,12 +74,10 @@ To remove a repository (repo is a short alias for repositories): ...@@ -74,12 +74,10 @@ To remove a repository (repo is a short alias for repositories):
def initialize(self, i, o): def initialize(self, i, o):
from poetry.utils._compat import decode from poetry.utils._compat import decode
super(ConfigCommand, self).initialize(i, o)
# Create config file if it does not exist # Create config file if it does not exist
if not self._config.file.exists(): if not self._settings_config.file.exists():
self._config.file.parent.mkdir(parents=True, exist_ok=True) self._settings_config.file.parent.mkdir(parents=True, exist_ok=True)
with self._config.file.open("w", encoding="utf-8") as f: with self._settings_config.file.open("w", encoding="utf-8") as f:
f.write(decode(TEMPLATE)) f.write(decode(TEMPLATE))
if not self._auth_config.file.exists(): if not self._auth_config.file.exists():
...@@ -89,7 +87,7 @@ To remove a repository (repo is a short alias for repositories): ...@@ -89,7 +87,7 @@ To remove a repository (repo is a short alias for repositories):
def handle(self): def handle(self):
if self.option("list"): if self.option("list"):
self._list_configuration(self._config.content) self._list_configuration(self._settings_config.content)
return 0 return 0
...@@ -106,10 +104,12 @@ To remove a repository (repo is a short alias for repositories): ...@@ -106,10 +104,12 @@ To remove a repository (repo is a short alias for repositories):
if m: if m:
if not m.group(1): if not m.group(1):
value = {} value = {}
if self._config.setting("repositories") is not None: if self._settings_config.setting("repositories") is not None:
value = self._config.setting("repositories") value = self._settings_config.setting("repositories")
else: else:
repo = self._config.setting("repositories.{}".format(m.group(1))) repo = self._settings_config.setting(
"repositories.{}".format(m.group(1))
)
if repo is None: if repo is None:
raise ValueError( raise ValueError(
"There is no {} repository defined".format(m.group(1)) "There is no {} repository defined".format(m.group(1))
...@@ -124,7 +124,9 @@ To remove a repository (repo is a short alias for repositories): ...@@ -124,7 +124,9 @@ To remove a repository (repo is a short alias for repositories):
raise ValueError("There is no {} setting.".format(setting_key)) raise ValueError("There is no {} setting.".format(setting_key))
values = self._get_setting( values = self._get_setting(
self._config.content, setting_key, default=values[setting_key][-1] self._settings_config.content,
setting_key,
default=values[setting_key][-1],
) )
for value in values: for value in values:
...@@ -150,20 +152,26 @@ To remove a repository (repo is a short alias for repositories): ...@@ -150,20 +152,26 @@ To remove a repository (repo is a short alias for repositories):
raise ValueError("You cannot remove the [repositories] section") raise ValueError("You cannot remove the [repositories] section")
if self.option("unset"): if self.option("unset"):
repo = self._config.setting("repositories.{}".format(m.group(1))) repo = self._settings_config.setting(
"repositories.{}".format(m.group(1))
)
if repo is None: if repo is None:
raise ValueError( raise ValueError(
"There is no {} repository defined".format(m.group(1)) "There is no {} repository defined".format(m.group(1))
) )
self._config.remove_property("repositories.{}".format(m.group(1))) self._settings_config.remove_property(
"repositories.{}".format(m.group(1))
)
return 0 return 0
if len(values) == 1: if len(values) == 1:
url = values[0] url = values[0]
self._config.add_property("repositories.{}.url".format(m.group(1)), url) self._settings_config.add_property(
"repositories.{}.url".format(m.group(1)), url
)
return 0 return 0
...@@ -222,12 +230,12 @@ To remove a repository (repo is a short alias for repositories): ...@@ -222,12 +230,12 @@ To remove a repository (repo is a short alias for repositories):
if not validator(value): if not validator(value):
raise RuntimeError('"{}" is an invalid value for {}'.format(value, key)) raise RuntimeError('"{}" is an invalid value for {}'.format(value, key))
self._config.add_property(key, normalizer(value)) self._settings_config.add_property(key, normalizer(value))
return 0 return 0
def _remove_single_value(self, key): def _remove_single_value(self, key):
self._config.remove_property(key) self._settings_config.remove_property(key)
return 0 return 0
......
from .info import DebugInfoCommand from .debug import DebugCommand
from .resolve import DebugResolveCommand
from ..command import Command
from .info import DebugInfoCommand
from .resolve import DebugResolveCommand
class DebugCommand(Command):
"""
Debug various elements of Poetry.
debug
"""
commands = [DebugInfoCommand().default(), DebugResolveCommand()]
...@@ -8,7 +8,7 @@ class DebugInfoCommand(Command): ...@@ -8,7 +8,7 @@ class DebugInfoCommand(Command):
""" """
Shows debug information. Shows debug information.
debug:info info
""" """
def handle(self): def handle(self):
...@@ -19,18 +19,17 @@ class DebugInfoCommand(Command): ...@@ -19,18 +19,17 @@ class DebugInfoCommand(Command):
poetry_python_version = ".".join(str(s) for s in sys.version_info[:3]) poetry_python_version = ".".join(str(s) for s in sys.version_info[:3])
self.output.title("Poetry") self.line("")
self.output.listing( self.line("<b>Poetry</b>")
[ self.line("")
"<info>Version</info>: <comment>{}</>".format(poetry.VERSION), self.line("<info>Version</info>: <comment>{}</>".format(poetry.VERSION))
"<info>Python</info>: <comment>{}</>".format(poetry_python_version), self.line("<info>Python</info>: <comment>{}</>".format(poetry_python_version))
]
)
self.line("") self.line("")
env_python_version = ".".join(str(s) for s in env.version_info[:3]) env_python_version = ".".join(str(s) for s in env.version_info[:3])
self.output.title("Virtualenv") self.line("<b>Virtualenv</b>")
self.line("")
listing = [ listing = [
"<info>Python</info>: <comment>{}</>".format(env_python_version), "<info>Python</info>: <comment>{}</>".format(env_python_version),
"<info>Implementation</info>: <comment>{}</>".format( "<info>Implementation</info>: <comment>{}</>".format(
...@@ -46,17 +45,21 @@ class DebugInfoCommand(Command): ...@@ -46,17 +45,21 @@ class DebugInfoCommand(Command):
tag="comment" if env.is_sane() else "error", is_valid=env.is_sane() tag="comment" if env.is_sane() else "error", is_valid=env.is_sane()
) )
) )
self.output.listing(listing)
for line in listing:
self.line(line)
self.line("") self.line("")
self.output.title("System") self.line("<b>System</b>")
self.output.listing( self.line("")
[ listing = [
"<info>Platform</info>: <comment>{}</>".format(sys.platform), "<info>Platform</info>: <comment>{}</>".format(sys.platform),
"<info>OS</info>: <comment>{}</>".format(os.name), "<info>OS</info>: <comment>{}</>".format(os.name),
"<info>Python</info>: <comment>{}</>".format(env.base), "<info>Python</info>: <comment>{}</>".format(env.base),
] ]
)
for line in listing:
self.line(line)
self.line("") self.line("")
...@@ -9,7 +9,7 @@ class DebugResolveCommand(Command): ...@@ -9,7 +9,7 @@ class DebugResolveCommand(Command):
""" """
Debugs dependency resolution. Debugs dependency resolution.
debug:resolve resolve
{ package?* : packages to resolve. } { package?* : packages to resolve. }
{ --E|extras=* : Extras to activate for the dependency. } { --E|extras=* : Extras to activate for the dependency. }
{ --python= : Python version(s) to use for resolution. } { --python= : Python version(s) to use for resolution. }
...@@ -17,7 +17,7 @@ class DebugResolveCommand(Command): ...@@ -17,7 +17,7 @@ class DebugResolveCommand(Command):
{ --install : Show what would be installed for the current system. } { --install : Show what would be installed for the current system. }
""" """
_loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self):
from poetry.packages import ProjectPackage from poetry.packages import ProjectPackage
...@@ -54,7 +54,7 @@ class DebugResolveCommand(Command): ...@@ -54,7 +54,7 @@ class DebugResolveCommand(Command):
pool = self.poetry.pool pool = self.poetry.pool
solver = Solver(package, pool, Repository(), Repository(), self.output) solver = Solver(package, pool, Repository(), Repository(), self._io)
ops = solver.solve() ops = solver.solve()
...@@ -63,9 +63,8 @@ class DebugResolveCommand(Command): ...@@ -63,9 +63,8 @@ class DebugResolveCommand(Command):
self.line("") self.line("")
if self.option("tree"): if self.option("tree"):
show_command = self.get_application().find("show") show_command = self.application.find("show")
show_command.output = self.output show_command.init_styles(self.io)
show_command.init_styles()
packages = [op.package for op in ops] packages = [op.package for op in ops]
repo = Repository(packages) repo = Repository(packages)
...@@ -74,7 +73,7 @@ class DebugResolveCommand(Command): ...@@ -74,7 +73,7 @@ class DebugResolveCommand(Command):
for pkg in repo.packages: for pkg in repo.packages:
for require in requires: for require in requires:
if pkg.name == require.name: if pkg.name == require.name:
show_command.display_package_tree(pkg, repo) show_command.display_package_tree(self.io, pkg, repo)
break break
return 0 return 0
......
...@@ -7,35 +7,9 @@ class EnvCommand(Command): ...@@ -7,35 +7,9 @@ class EnvCommand(Command):
super(EnvCommand, self).__init__() super(EnvCommand, self).__init__()
def initialize(self, i, o):
from poetry.semver import parse_constraint
from poetry.utils.env import Env
super(EnvCommand, self).initialize(i, o)
# Checking compatibility of the current environment with
# the python dependency specified in pyproject.toml
current_env = Env.get(self.poetry.file.parent)
supported_python = self.poetry.package.python_constraint
current_python = parse_constraint(
".".join(str(v) for v in current_env.version_info[:3])
)
if not supported_python.allows(current_python):
raise RuntimeError(
"The current Python version ({}) is not supported by the project ({})\n"
"Please activate a compatible Python version.".format(
current_python, self.poetry.package.python_versions
)
)
self._env = Env.create_venv(
self.poetry.file.parent, o, self.poetry.package.name
)
if self._env.is_venv() and o.is_verbose():
o.writeln("Using virtualenv: <comment>{}</>".format(self._env.path))
@property @property
def env(self): def env(self):
return self._env return self._env
def set_env(self, env):
self._env = env
...@@ -23,11 +23,11 @@ class ExportCommand(Command): ...@@ -23,11 +23,11 @@ class ExportCommand(Command):
if not locker.is_locked(): if not locker.is_locked():
self.line("<comment>The lock file does not exist. Locking.</comment>") self.line("<comment>The lock file does not exist. Locking.</comment>")
options = [] options = []
if self.output.is_debug(): if self.io.is_debug():
options.append(("-vvv", None)) options.append(("-vvv", None))
elif self.output.is_very_verbose(): elif self.io.is_very_verbose():
options.append(("-vv", None)) options.append(("-vv", None))
elif self.output.is_verbose(): elif self.io.is_verbose():
options.append(("-v", None)) options.append(("-v", None))
self.call("lock", options) self.call("lock", options)
......
...@@ -41,18 +41,16 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -41,18 +41,16 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
from poetry.vcs.git import GitConfig from poetry.vcs.git import GitConfig
if (Path.cwd() / "pyproject.toml").exists(): if (Path.cwd() / "pyproject.toml").exists():
self.error("A pyproject.toml file already exists.") self.line("<error>A pyproject.toml file already exists.</error>")
return 1 return 1
vcs_config = GitConfig() vcs_config = GitConfig()
self.line("")
self.line( self.line(
[ "This command will guide you through creating your <info>pyproject.toml</> config."
"",
"This command will guide you through creating your <info>pyproject.toml</> config.",
"",
]
) )
self.line("")
name = self.option("name") name = self.option("name")
if not name: if not name:
...@@ -86,7 +84,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -86,7 +84,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
question = self.create_question( question = self.create_question(
"Author [<comment>{}</comment>, n to skip]: ".format(author), default=author "Author [<comment>{}</comment>, n to skip]: ".format(author), default=author
) )
question.validator = lambda v: self._validate_author(v, author) question.set_validator(lambda v: self._validate_author(v, author))
author = self.ask(question) author = self.ask(question)
if not author: if not author:
...@@ -99,7 +97,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -99,7 +97,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
question = self.create_question( question = self.create_question(
"License [<comment>{}</comment>]: ".format(license), default=license "License [<comment>{}</comment>]: ".format(license), default=license
) )
question.validator = self._validate_license question.set_validator(self._validate_license)
license = self.ask(question) license = self.ask(question)
current_env = Env.get(Path.cwd()) current_env = Env.get(Path.cwd())
...@@ -125,6 +123,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -125,6 +123,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
requirements = self._format_requirements( requirements = self._format_requirements(
self._determine_requirements(self.option("dependency")) self._determine_requirements(self.option("dependency"))
) )
self.line("")
dev_requirements = {} dev_requirements = {}
...@@ -136,6 +135,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -136,6 +135,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
dev_requirements = self._format_requirements( dev_requirements = self._format_requirements(
self._determine_requirements(self.option("dev-dependency")) self._determine_requirements(self.option("dev-dependency"))
) )
self.line("")
layout_ = layout("standard")( layout_ = layout("standard")(
name, name,
...@@ -149,9 +149,11 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -149,9 +149,11 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
) )
content = layout_.generate_poetry_content() content = layout_.generate_poetry_content()
if self.input.is_interactive(): if self.io.is_interactive():
self.line("<info>Generated file</info>") self.line("<info>Generated file</info>")
self.line(["", content, ""]) self.line("")
self.line(content)
self.line("")
if not self.confirm("Do you confirm generation?", True): if not self.confirm("Do you confirm generation?", True):
self.line("<error>Command aborted</error>") self.line("<error>Command aborted</error>")
...@@ -203,7 +205,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in ...@@ -203,7 +205,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
constraint = self.ask(question) constraint = self.ask(question)
if constraint is False: if constraint is None:
_, constraint = self._find_best_version_for_package(package) _, constraint = self._find_best_version_for_package(package)
self.line( self.line(
......
...@@ -26,19 +26,15 @@ exist it will look for <comment>pyproject.toml</> and do the same. ...@@ -26,19 +26,15 @@ exist it will look for <comment>pyproject.toml</> and do the same.
_loggers = ["poetry.repositories.pypi_repository"] _loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self):
from clikit.io import NullIO
from poetry.installation import Installer from poetry.installation import Installer
from poetry.io import NullIO
from poetry.masonry.builders import SdistBuilder from poetry.masonry.builders import SdistBuilder
from poetry.masonry.utils.module import ModuleOrPackageNotFound from poetry.masonry.utils.module import ModuleOrPackageNotFound
from poetry.utils._compat import decode from poetry.utils._compat import decode
from poetry.utils.env import NullEnv from poetry.utils.env import NullEnv
installer = Installer( installer = Installer(
self.output, self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
) )
extras = [] extras = []
......
...@@ -20,11 +20,7 @@ the current directory, processes it, and locks the depdencies in the <comment>po ...@@ -20,11 +20,7 @@ the current directory, processes it, and locks the depdencies in the <comment>po
from poetry.installation import Installer from poetry.installation import Installer
installer = Installer( installer = Installer(
self.output, self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
) )
installer.update(True) installer.update(True)
......
...@@ -24,7 +24,7 @@ the config command. ...@@ -24,7 +24,7 @@ the config command.
def handle(self): def handle(self):
from poetry.masonry.publishing.publisher import Publisher from poetry.masonry.publishing.publisher import Publisher
publisher = Publisher(self.poetry, self.output) publisher = Publisher(self.poetry, self.io)
# Building package first, if told # Building package first, if told
if self.option("build"): if self.option("build"):
......
...@@ -17,7 +17,7 @@ list of installed packages ...@@ -17,7 +17,7 @@ list of installed packages
<info>poetry remove</info>""" <info>poetry remove</info>"""
_loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self):
from poetry.installation import Installer from poetry.installation import Installer
...@@ -55,11 +55,7 @@ list of installed packages ...@@ -55,11 +55,7 @@ list of installed packages
self.reset_poetry() self.reset_poetry()
installer = Installer( installer = Installer(
self.output, self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
) )
installer.dry_run(self.option("dry-run")) installer.dry_run(self.option("dry-run"))
......
...@@ -9,6 +9,13 @@ class RunCommand(EnvCommand): ...@@ -9,6 +9,13 @@ class RunCommand(EnvCommand):
{ args* : The command and arguments/options to run. } { args* : The command and arguments/options to run. }
""" """
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): def handle(self):
args = self.argument("args") args = self.argument("args")
script = args[0] script = args[0]
...@@ -48,22 +55,5 @@ class RunCommand(EnvCommand): ...@@ -48,22 +55,5 @@ class RunCommand(EnvCommand):
package = poetry.package package = poetry.package
path = poetry.file.parent path = poetry.file.parent
module = Module(package.name, path.as_posix(), package.packages) module = Module(package.name, path.as_posix(), package.packages)
return module
def merge_application_definition(self, merge_args=True): return module
if self._application is None or (
self._application_definition_merged
and (self._application_definition_merged_with_args or not merge_args)
):
return
if merge_args:
current_arguments = self._definition.get_arguments()
self._definition.set_arguments(
self._application.get_definition().get_arguments()
)
self._definition.add_arguments(current_arguments)
self._application_definition_merged = True
if merge_args:
self._application_definition_merged_with_args = True
...@@ -52,22 +52,5 @@ class ScriptCommand(EnvCommand): ...@@ -52,22 +52,5 @@ class ScriptCommand(EnvCommand):
package = poetry.package package = poetry.package
path = poetry.file.parent path = poetry.file.parent
module = Module(package.name, path.as_posix()) module = Module(package.name, path.as_posix())
return module
def merge_application_definition(self, merge_args=True):
if self._application is None or (
self._application_definition_merged
and (self._application_definition_merged_with_args or not merge_args)
):
return
if merge_args:
current_arguments = self._definition.get_arguments()
self._definition.set_arguments(
self._application.get_definition().get_arguments()
)
self._definition.add_arguments(current_arguments)
self._application_definition_merged = True return module
if merge_args:
self._application_definition_merged_with_args = True
from .update import SelfUpdateCommand from .self import SelfCommand
from ..command import Command
from .update import SelfUpdateCommand
class SelfCommand(Command):
"""
Interact with Poetry directly.
"""
name = "self"
commands = [SelfUpdateCommand()]
def handle(self):
return self.call("help", self._config.name)
...@@ -22,7 +22,7 @@ class SelfUpdateCommand(Command): ...@@ -22,7 +22,7 @@ class SelfUpdateCommand(Command):
""" """
Updates poetry to the latest version. Updates poetry to the latest version.
self:update update
{ version? : The version to update to. } { version? : The version to update to. }
{ --preview : Install prereleases. } { --preview : Install prereleases. }
""" """
...@@ -51,7 +51,6 @@ class SelfUpdateCommand(Command): ...@@ -51,7 +51,6 @@ class SelfUpdateCommand(Command):
from poetry.repositories.pypi_repository import PyPiRepository from poetry.repositories.pypi_repository import PyPiRepository
from poetry.semver import Version from poetry.semver import Version
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import decode
current = Path(__file__) current = Path(__file__)
try: try:
...@@ -104,20 +103,7 @@ class SelfUpdateCommand(Command): ...@@ -104,20 +103,7 @@ class SelfUpdateCommand(Command):
self.line("You are using the latest version") self.line("You are using the latest version")
return return
try: self.update(release)
self.update(release)
except subprocess.CalledProcessError as e:
self.line("")
self.output.block(
[
"[CalledProcessError]",
"An error has occured: {}".format(str(e)),
decode(e.output),
],
style="error",
)
return e.returncode
def update(self, release): def update(self, release):
version = release.version version = release.version
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
from .env_command import EnvCommand from .env_command import EnvCommand
...@@ -24,16 +22,17 @@ lists all packages available.""" ...@@ -24,16 +22,17 @@ lists all packages available."""
colors = ["green", "yellow", "cyan", "magenta", "blue"] colors = ["green", "yellow", "cyan", "magenta", "blue"]
def handle(self): def handle(self):
from clikit.utils.terminal import Terminal
from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.installed_repository import InstalledRepository
from poetry.semver import Version from poetry.semver import Version
package = self.argument("package") package = self.argument("package")
if self.option("tree"): if self.option("tree"):
self.init_styles() self.init_styles(self.io)
if self.option("outdated"): if self.option("outdated"):
self.input.set_option("latest", True) self._args.set_option("latest", True)
include_dev = not self.option("no-dev") include_dev = not self.option("no-dev")
locked_repo = self.poetry.locker.locked_repository(include_dev) locked_repo = self.poetry.locker.locked_repository(include_dev)
...@@ -45,13 +44,13 @@ lists all packages available.""" ...@@ -45,13 +44,13 @@ lists all packages available."""
for package in packages: for package in packages:
for require in requires: for require in requires:
if package.name == require.name: if package.name == require.name:
self.display_package_tree(package, locked_repo) self.display_package_tree(self._io, package, locked_repo)
break break
return 0 return 0
table = self.table(style="compact") table = self.table(style="compact")
table.get_style().set_vertical_border_char("") # table.style.line_vc_char = ""
locked_packages = locked_repo.packages locked_packages = locked_repo.packages
if package: if package:
...@@ -65,7 +64,7 @@ lists all packages available.""" ...@@ -65,7 +64,7 @@ lists all packages available."""
raise ValueError("Package {} not found".format(package)) raise ValueError("Package {} not found".format(package))
if self.option("tree"): if self.option("tree"):
self.display_package_tree(pkg, locked_repo) self.display_package_tree(self.io, pkg, locked_repo)
return 0 return 0
...@@ -92,7 +91,7 @@ lists all packages available.""" ...@@ -92,7 +91,7 @@ lists all packages available."""
show_latest = self.option("latest") show_latest = self.option("latest")
show_all = self.option("all") show_all = self.option("all")
terminal = self.get_application().terminal terminal = Terminal()
width = terminal.width width = terminal.width
name_length = version_length = latest_length = 0 name_length = version_length = latest_length = 0
latest_packages = {} latest_packages = {}
...@@ -114,7 +113,7 @@ lists all packages available.""" ...@@ -114,7 +113,7 @@ lists all packages available."""
continue continue
current_length = len(locked.pretty_name) current_length = len(locked.pretty_name)
if not self.output.is_decorated(): if not self._io.output.supports_ansi():
installed_status = self.get_installed_status(locked, installed_repo) installed_status = self.get_installed_status(locked, installed_repo)
if installed_status == "not-installed": if installed_status == "not-installed":
...@@ -158,7 +157,7 @@ lists all packages available.""" ...@@ -158,7 +157,7 @@ lists all packages available."""
if installed_status == "not-installed": if installed_status == "not-installed":
color = "red" color = "red"
if not self.output.is_decorated(): if not self._io.output.supports_ansi():
# Non installed in non decorated mode # Non installed in non decorated mode
install_marker = " (!)" install_marker = " (!)"
...@@ -200,13 +199,13 @@ lists all packages available.""" ...@@ -200,13 +199,13 @@ lists all packages available."""
self.line(line) self.line(line)
def display_package_tree(self, package, installed_repo): def display_package_tree(self, io, package, installed_repo):
self.write("<info>{}</info>".format(package.pretty_name)) io.write("<info>{}</info>".format(package.pretty_name))
description = "" description = ""
if package.description: if package.description:
description = " " + package.description description = " " + package.description
self.line(" {}{}".format(package.pretty_version, description)) io.write_line(" {}{}".format(package.pretty_version, description))
dependencies = package.requires dependencies = package.requires
dependencies = sorted(dependencies, key=lambda x: x.name) dependencies = sorted(dependencies, key=lambda x: x.name)
...@@ -226,17 +225,18 @@ lists all packages available.""" ...@@ -226,17 +225,18 @@ lists all packages available."""
name=dependency.name, name=dependency.name,
constraint=dependency.pretty_constraint, constraint=dependency.pretty_constraint,
) )
self._write_tree_line(info) self._write_tree_line(io, info)
tree_bar = tree_bar.replace("└", " ") tree_bar = tree_bar.replace("└", " ")
packages_in_tree = [package.name, dependency.name] packages_in_tree = [package.name, dependency.name]
self._display_tree( self._display_tree(
dependency, installed_repo, packages_in_tree, tree_bar, level + 1 io, dependency, installed_repo, packages_in_tree, tree_bar, level + 1
) )
def _display_tree( def _display_tree(
self, self,
io,
dependency, dependency,
installed_repo, installed_repo,
packages_in_tree, packages_in_tree,
...@@ -276,7 +276,7 @@ lists all packages available.""" ...@@ -276,7 +276,7 @@ lists all packages available."""
constraint=dependency.pretty_constraint, constraint=dependency.pretty_constraint,
warn=circular_warn, warn=circular_warn,
) )
self._write_tree_line(info) self._write_tree_line(io, info)
tree_bar = tree_bar.replace("└", " ") tree_bar = tree_bar.replace("└", " ")
...@@ -284,24 +284,28 @@ lists all packages available.""" ...@@ -284,24 +284,28 @@ lists all packages available."""
current_tree.append(dependency.name) current_tree.append(dependency.name)
self._display_tree( self._display_tree(
dependency, installed_repo, current_tree, tree_bar, level + 1 io, dependency, installed_repo, current_tree, tree_bar, level + 1
) )
def _write_tree_line(self, line): def _write_tree_line(self, io, line):
if not self.output.is_decorated(): if not io.output.supports_ansi():
line = line.replace("└", "`-") line = line.replace("└", "`-")
line = line.replace("├", "|-") line = line.replace("├", "|-")
line = line.replace("──", "-") line = line.replace("──", "-")
line = line.replace("│", "|") line = line.replace("│", "|")
self.line(line) io.write_line(line)
def init_styles(self, io):
from clikit.api.formatter import Style
def init_styles(self):
for color in self.colors: for color in self.colors:
self.set_style(color, color) style = Style(color).fg(color)
io.output.formatter.add_style(style)
io.error_output.formatter.add_style(style)
def find_latest_package(self, package, include_dev): def find_latest_package(self, package, include_dev):
from poetry.io import NullIO from clikit.io import NullIO
from poetry.puzzle.provider import Provider from poetry.puzzle.provider import Provider
from poetry.version.version_selector import VersionSelector from poetry.version.version_selector import VersionSelector
......
...@@ -13,7 +13,7 @@ class UpdateCommand(EnvCommand): ...@@ -13,7 +13,7 @@ class UpdateCommand(EnvCommand):
{ --lock : Do not perform install (only update the lockfile). } { --lock : Do not perform install (only update the lockfile). }
""" """
_loggers = ["poetry.repositories.pypi_repository"] loggers = ["poetry.repositories.pypi_repository"]
def handle(self): def handle(self):
from poetry.installation import Installer from poetry.installation import Installer
...@@ -21,11 +21,7 @@ class UpdateCommand(EnvCommand): ...@@ -21,11 +21,7 @@ class UpdateCommand(EnvCommand):
packages = self.argument("packages") packages = self.argument("packages")
installer = Installer( installer = Installer(
self.output, self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
) )
if packages: if packages:
......
import re
from .command import Command from .command import Command
...@@ -8,7 +6,7 @@ class VersionCommand(Command): ...@@ -8,7 +6,7 @@ class VersionCommand(Command):
Bumps the version of the project. Bumps the version of the project.
version version
{ version=patch } { version=patch : The version number or the rule to update version }
""" """
help = """\ help = """\
......
from .application_config import ApplicationConfig
import logging
from cleo.config import ApplicationConfig as BaseApplicationConfig
from clikit.api.event import ConsoleEvents
from clikit.api.event import PreHandleEvent
from clikit.api.formatter import Style
from poetry.console.commands.command import Command
from poetry.console.commands.env_command import EnvCommand
from poetry.console.logging import IOFormatter
from poetry.console.logging import IOHandler
class ApplicationConfig(BaseApplicationConfig):
def configure(self):
super(ApplicationConfig, self).configure()
self.add_style(Style("c1").fg("green"))
self.add_style(Style("comment").fg("cyan"))
self.add_style(Style("error").fg("red").bold())
self.add_style(Style("warning").fg("yellow"))
self.add_style(Style("debug").fg("black").bold())
self.add_event_listener(
ConsoleEvents.PRE_HANDLE.value, self.register_command_loggers
)
self.add_event_listener(ConsoleEvents.PRE_HANDLE.value, self.set_env)
def register_command_loggers(
self, event, event_name, _
): # type: (PreHandleEvent, str, ...) -> None
command = event.command.config.handler
if not isinstance(command, Command):
return
io = event.io
if not command.loggers:
return
handler = IOHandler(io)
handler.setFormatter(IOFormatter())
for logger in command.loggers:
logger = logging.getLogger(logger)
logger.handlers = [handler]
logger.propagate = False
level = logging.WARNING
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, ...) -> None
from poetry.semver import parse_constraint
from poetry.utils.env import Env
command = event.command.config.handler
if not isinstance(command, EnvCommand):
return
io = event.io
poetry = command.poetry
# Checking compatibility of the current environment with
# the python dependency specified in pyproject.toml
current_env = Env.get(poetry.file.parent)
supported_python = poetry.package.python_constraint
current_python = parse_constraint(
".".join(str(v) for v in current_env.version_info[:3])
)
if not supported_python.allows(current_python):
raise RuntimeError(
"The current Python version ({}) is not supported by the project ({})\n"
"Please activate a compatible Python version.".format(
current_python, poetry.package.python_versions
)
)
env = Env.create_venv(poetry.file.parent, io, poetry.package.name)
if env.is_venv() and io.is_verbose():
io.write_line("Using virtualenv: <comment>{}</>".format(env.path))
command.set_env(env)
from .io_formatter import IOFormatter
from .io_handler import IOHandler
import logging
class IOFormatter(logging.Formatter):
_colors = {
"error": "fg=red",
"warning": "fg=yellow",
"debug": "debug",
"info": "fg=blue",
}
def format(self, record):
if not record.exc_info:
level = record.levelname.lower()
msg = record.msg
if level in self._colors:
msg = "<{}>{}</>".format(self._colors[level], msg)
return msg
return super(IOFormatter, self).format(record)
import logging
class IOHandler(logging.Handler):
def __init__(self, io):
self._io = io
level = logging.WARNING
if io.is_debug():
level = logging.DEBUG
elif io.is_very_verbose() or io.is_verbose():
level = logging.INFO
super(IOHandler, self).__init__(level)
def emit(self, record):
try:
msg = self.format(record)
level = record.levelname.lower()
err = level in ("warning", "error", "exception", "critical")
if err:
self._io.error(msg, newline=True)
else:
self._io.write_line(msg)
except Exception:
self.handleError(record)
from cleo.styles import CleoStyle
from cleo.styles import OutputStyle
class PoetryStyle(CleoStyle):
def __init__(self, i, o):
super(PoetryStyle, self).__init__(i, o)
self.output.get_formatter().add_style("error", "red")
self.output.get_formatter().add_style("warning", "yellow")
self.output.get_formatter().add_style("question", "blue")
self.output.get_formatter().add_style("comment", "cyan")
self.output.get_formatter().add_style("debug", "black", options=["bold"])
def writeln(
self,
messages,
type=OutputStyle.OUTPUT_NORMAL,
verbosity=OutputStyle.VERBOSITY_NORMAL,
):
if self.output.verbosity >= verbosity:
super(PoetryStyle, self).writeln(messages, type=type)
def write(
self,
messages,
newline=False,
type=OutputStyle.OUTPUT_NORMAL,
verbosity=OutputStyle.VERBOSITY_NORMAL,
):
if self.output.verbosity >= verbosity:
super(PoetryStyle, self).write(messages, newline=newline, type=type)
import sys
from typing import List from typing import List
from typing import Union from typing import Union
from poetry.io import NullIO from clikit.api.io import IO
from clikit.io import NullIO
from poetry.packages import Dependency from poetry.packages import Dependency
from poetry.packages import Locker from poetry.packages import Locker
from poetry.packages import Package from poetry.packages import Package
from poetry.packages.constraints import parse_constraint as parse_generic_constraint
from poetry.puzzle import Solver from poetry.puzzle import Solver
from poetry.puzzle.operations import Install from poetry.puzzle.operations import Install
from poetry.puzzle.operations import Uninstall from poetry.puzzle.operations import Uninstall
...@@ -17,7 +16,6 @@ from poetry.repositories import Pool ...@@ -17,7 +16,6 @@ from poetry.repositories import Pool
from poetry.repositories import Repository from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.installed_repository import InstalledRepository
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
from poetry.semver import Version
from poetry.utils.helpers import canonicalize_name from poetry.utils.helpers import canonicalize_name
from .base_installer import BaseInstaller from .base_installer import BaseInstaller
...@@ -27,7 +25,7 @@ from .pip_installer import PipInstaller ...@@ -27,7 +25,7 @@ from .pip_installer import PipInstaller
class Installer: class Installer:
def __init__( def __init__(
self, self,
io, io, # type: IO
env, env,
package, # type: Package package, # type: Package
locker, # type: Locker locker, # type: Locker
...@@ -146,7 +144,7 @@ class Installer: ...@@ -146,7 +144,7 @@ class Installer:
if extra not in self._package.extras: if extra not in self._package.extras:
raise ValueError("Extra [{}] is not specified.".format(extra)) raise ValueError("Extra [{}] is not specified.".format(extra))
self._io.writeln("<info>Updating dependencies</>") self._io.write_line("<info>Updating dependencies</>")
solver = Solver( solver = Solver(
self._package, self._package,
self._pool, self._pool,
...@@ -157,12 +155,12 @@ class Installer: ...@@ -157,12 +155,12 @@ class Installer:
ops = solver.solve(use_latest=self._whitelist) ops = solver.solve(use_latest=self._whitelist)
else: else:
self._io.writeln("<info>Installing dependencies from lock file</>") self._io.write_line("<info>Installing dependencies from lock file</>")
locked_repository = self._locker.locked_repository(True) locked_repository = self._locker.locked_repository(True)
if not self._locker.is_fresh(): if not self._locker.is_fresh():
self._io.writeln( self._io.write_line(
"<warning>" "<warning>"
"Warning: The lock file is not up to date with " "Warning: The lock file is not up to date with "
"the latest changes in pyproject.toml. " "the latest changes in pyproject.toml. "
...@@ -220,12 +218,12 @@ class Installer: ...@@ -220,12 +218,12 @@ class Installer:
# or optional and not requested, are dropped # or optional and not requested, are dropped
self._filter_operations(ops, local_repo) self._filter_operations(ops, local_repo)
self._io.new_line() self._io.write_line("")
# Execute operations # Execute operations
actual_ops = [op for op in ops if not op.skipped] actual_ops = [op for op in ops if not op.skipped]
if not actual_ops and (self._execute_operations or self._dry_run): if not actual_ops and (self._execute_operations or self._dry_run):
self._io.writeln("Nothing to install or update") self._io.write_line("Nothing to install or update")
if actual_ops and (self._execute_operations or self._dry_run): if actual_ops and (self._execute_operations or self._dry_run):
installs = [] installs = []
...@@ -253,8 +251,8 @@ class Installer: ...@@ -253,8 +251,8 @@ class Installer:
elif op.job_type == "uninstall": elif op.job_type == "uninstall":
uninstalls.append(op.package.pretty_name) uninstalls.append(op.package.pretty_name)
self._io.new_line() self._io.write_line("")
self._io.writeln( self._io.write_line(
"Package operations: " "Package operations: "
"<info>{}</> install{}, " "<info>{}</> install{}, "
"<info>{}</> update{}, " "<info>{}</> update{}, "
...@@ -279,10 +277,10 @@ class Installer: ...@@ -279,10 +277,10 @@ class Installer:
) )
if updated_lock: if updated_lock:
self._io.writeln("") self._io.write_line("")
self._io.writeln("<info>Writing lock file</>") self._io.write_line("<info>Writing lock file</>")
self._io.writeln("") self._io.write_line("")
for op in ops: for op in ops:
self._execute(op) self._execute(op)
...@@ -297,7 +295,7 @@ class Installer: ...@@ -297,7 +295,7 @@ class Installer:
def _execute_install(self, operation): # type: (Install) -> None def _execute_install(self, operation): # type: (Install) -> None
if operation.skipped: if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()): if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.writeln( self._io.write_line(
" - Skipping <info>{}</> (<comment>{}</>) {}".format( " - Skipping <info>{}</> (<comment>{}</>) {}".format(
operation.package.pretty_name, operation.package.pretty_name,
operation.package.full_pretty_version, operation.package.full_pretty_version,
...@@ -308,7 +306,7 @@ class Installer: ...@@ -308,7 +306,7 @@ class Installer:
return return
if self._execute_operations or self.is_dry_run(): if self._execute_operations or self.is_dry_run():
self._io.writeln( self._io.write_line(
" - Installing <info>{}</> (<comment>{}</>)".format( " - Installing <info>{}</> (<comment>{}</>)".format(
operation.package.pretty_name, operation.package.full_pretty_version operation.package.pretty_name, operation.package.full_pretty_version
) )
...@@ -325,7 +323,7 @@ class Installer: ...@@ -325,7 +323,7 @@ class Installer:
if operation.skipped: if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()): if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.writeln( self._io.write_line(
" - Skipping <info>{}</> (<comment>{}</>) {}".format( " - Skipping <info>{}</> (<comment>{}</>) {}".format(
target.pretty_name, target.pretty_name,
target.full_pretty_version, target.full_pretty_version,
...@@ -336,7 +334,7 @@ class Installer: ...@@ -336,7 +334,7 @@ class Installer:
return return
if self._execute_operations or self.is_dry_run(): if self._execute_operations or self.is_dry_run():
self._io.writeln( self._io.write_line(
" - Updating <info>{}</> (<comment>{}</> -> <comment>{}</>)".format( " - Updating <info>{}</> (<comment>{}</> -> <comment>{}</>)".format(
target.pretty_name, target.pretty_name,
source.full_pretty_version, source.full_pretty_version,
...@@ -352,7 +350,7 @@ class Installer: ...@@ -352,7 +350,7 @@ class Installer:
def _execute_uninstall(self, operation): # type: (Uninstall) -> None def _execute_uninstall(self, operation): # type: (Uninstall) -> None
if operation.skipped: if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()): if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.writeln( self._io.write_line(
" - Not removing <info>{}</> (<comment>{}</>) {}".format( " - Not removing <info>{}</> (<comment>{}</>) {}".format(
operation.package.pretty_name, operation.package.pretty_name,
operation.package.full_pretty_version, operation.package.full_pretty_version,
...@@ -363,7 +361,7 @@ class Installer: ...@@ -363,7 +361,7 @@ class Installer:
return return
if self._execute_operations or self.is_dry_run(): if self._execute_operations or self.is_dry_run():
self._io.writeln( self._io.write_line(
" - Removing <info>{}</> (<comment>{}</>)".format( " - Removing <info>{}</> (<comment>{}</>)".format(
operation.package.pretty_name, operation.package.full_pretty_version operation.package.pretty_name, operation.package.full_pretty_version
) )
......
import os import os
import shutil
import tempfile import tempfile
from subprocess import CalledProcessError from subprocess import CalledProcessError
from clikit.io import NullIO
from poetry.config import Config from poetry.config import Config
from poetry.utils.helpers import get_http_basic_auth from poetry.utils.helpers import get_http_basic_auth
from poetry.utils.helpers import safe_rmtree from poetry.utils.helpers import safe_rmtree
...@@ -41,7 +42,7 @@ class PipInstaller(BaseInstaller): ...@@ -41,7 +42,7 @@ class PipInstaller(BaseInstaller):
if package.source_type == "legacy" and package.source_url: if package.source_type == "legacy" and package.source_url:
parsed = urlparse.urlparse(package.source_url) parsed = urlparse.urlparse(package.source_url)
if parsed.scheme == "http": if parsed.scheme == "http":
self._io.write_error( self._io.error(
" <warning>Installing from unsecure host: {}</warning>".format( " <warning>Installing from unsecure host: {}</warning>".format(
parsed.hostname parsed.hostname
) )
...@@ -152,7 +153,6 @@ class PipInstaller(BaseInstaller): ...@@ -152,7 +153,6 @@ class PipInstaller(BaseInstaller):
return name return name
def install_directory(self, package): def install_directory(self, package):
from poetry.io import NullIO
from poetry.masonry.builder import SdistBuilder from poetry.masonry.builder import SdistBuilder
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import decode from poetry.utils._compat import decode
......
from .null_io import NullIO
from cleo.inputs import ListInput
from cleo.outputs import NullOutput
from poetry.console.styles.poetry import PoetryStyle
class NullIO(PoetryStyle):
def __init__(self):
super(NullIO, self).__init__(ListInput([]), NullOutput())
def is_quiet(self): # type: () -> bool
return False
def is_verbose(self): # type: () -> bool
return False
def is_very_verbose(self): # type: () -> bool
return False
def is_debug(self): # type: () -> bool
return False
def writeln(self, *args, **kwargs):
pass
def write(self, *args, **kwargs):
pass
def new_line(self, *args, **kwargs):
pass
import sys
from cleo.inputs import ArgvInput
class RawArgvInput(ArgvInput):
def parse(self):
self._parsed = self._tokens
while True:
try:
token = self._parsed.pop(0)
except IndexError:
break
self.parse_argument(token)
...@@ -4,8 +4,9 @@ PEP-517 compliant buildsystem API ...@@ -4,8 +4,9 @@ PEP-517 compliant buildsystem API
import logging import logging
import sys import sys
from clikit.io import NullIO
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.io import NullIO
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import unicode from poetry.utils._compat import unicode
from poetry.utils.env import SystemEnv from poetry.utils.env import SystemEnv
......
...@@ -8,6 +8,8 @@ from contextlib import contextmanager ...@@ -8,6 +8,8 @@ from contextlib import contextmanager
from typing import Set from typing import Set
from typing import Union from typing import Union
from clikit.api.io.flags import VERY_VERBOSE
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils._compat import basestring from poetry.utils._compat import basestring
from poetry.utils._compat import lru_cache from poetry.utils._compat import lru_cache
...@@ -98,26 +100,24 @@ class Builder(object): ...@@ -98,26 +100,24 @@ class Builder(object):
# Skip duplicates # Skip duplicates
continue continue
self._io.writeln( self._io.write_line(
" - Adding: <comment>{}</comment>".format(str(file)), " - Adding: <comment>{}</comment>".format(str(file)), VERY_VERBOSE
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
) )
to_add.append(file) to_add.append(file)
# Include project files # Include project files
self._io.writeln( self._io.write_line(
" - Adding: <comment>pyproject.toml</comment>", " - Adding: <comment>pyproject.toml</comment>", VERY_VERBOSE
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
) )
to_add.append(Path("pyproject.toml")) to_add.append(Path("pyproject.toml"))
# If a license file exists, add it # If a license file exists, add it
for license_file in self._path.glob("LICENSE*"): for license_file in self._path.glob("LICENSE*"):
self._io.writeln( self._io.write_line(
" - Adding: <comment>{}</comment>".format( " - Adding: <comment>{}</comment>".format(
license_file.relative_to(self._path) license_file.relative_to(self._path)
), ),
verbosity=self._io.VERBOSITY_VERY_VERBOSE, VERY_VERBOSE,
) )
to_add.append(license_file.relative_to(self._path)) to_add.append(license_file.relative_to(self._path))
...@@ -126,11 +126,11 @@ class Builder(object): ...@@ -126,11 +126,11 @@ class Builder(object):
if "readme" in self._poetry.local_config: if "readme" in self._poetry.local_config:
readme = self._path / self._poetry.local_config["readme"] readme = self._path / self._poetry.local_config["readme"]
if readme.exists(): if readme.exists():
self._io.writeln( self._io.write_line(
" - Adding: <comment>{}</comment>".format( " - Adding: <comment>{}</comment>".format(
readme.relative_to(self._path) readme.relative_to(self._path)
), ),
verbosity=self._io.VERBOSITY_VERY_VERBOSE, VERY_VERBOSE,
) )
to_add.append(readme.relative_to(self._path)) to_add.append(readme.relative_to(self._path))
......
...@@ -17,7 +17,7 @@ class CompleteBuilder(Builder): ...@@ -17,7 +17,7 @@ class CompleteBuilder(Builder):
sdist_builder = SdistBuilder(self._poetry, self._env, self._io) sdist_builder = SdistBuilder(self._poetry, self._env, self._io)
sdist_file = sdist_builder.build() sdist_file = sdist_builder.build()
self._io.writeln("") self._io.write_line("")
dist_dir = self._path / "dist" dist_dir = self._path / "dist"
with self.unpacked_tarball(sdist_file) as tmpdir: with self.unpacked_tarball(sdist_file) as tmpdir:
......
...@@ -54,7 +54,7 @@ Author-email: {author_email} ...@@ -54,7 +54,7 @@ Author-email: {author_email}
class SdistBuilder(Builder): class SdistBuilder(Builder):
def build(self, target_dir=None): # type: (Path) -> Path def build(self, target_dir=None): # type: (Path) -> Path
self._io.writeln(" - Building <info>sdist</info>") self._io.write_line(" - Building <info>sdist</info>")
if target_dir is None: if target_dir is None:
target_dir = self._path / "dist" target_dir = self._path / "dist"
...@@ -101,7 +101,7 @@ class SdistBuilder(Builder): ...@@ -101,7 +101,7 @@ class SdistBuilder(Builder):
tar.close() tar.close()
gz.close() gz.close()
self._io.writeln(" - Built <fg=cyan>{}</>".format(target.name)) self._io.write_line(" - Built <fg=cyan>{}</>".format(target.name))
return target return target
......
...@@ -13,6 +13,8 @@ from base64 import urlsafe_b64encode ...@@ -13,6 +13,8 @@ from base64 import urlsafe_b64encode
from io import StringIO from io import StringIO
from typing import Set from typing import Set
from clikit.api.io.flags import VERY_VERBOSE
from poetry.__version__ import __version__ from poetry.__version__ import __version__
from poetry.semver import parse_constraint from poetry.semver import parse_constraint
...@@ -56,7 +58,7 @@ class WheelBuilder(Builder): ...@@ -56,7 +58,7 @@ class WheelBuilder(Builder):
cls.make_in(poetry, env, io) cls.make_in(poetry, env, io)
def build(self): def build(self):
self._io.writeln(" - Building <info>wheel</info>") self._io.write_line(" - Building <info>wheel</info>")
dist_dir = self._target_dir dist_dir = self._target_dir
if not dist_dir.exists(): if not dist_dir.exists():
...@@ -77,7 +79,7 @@ class WheelBuilder(Builder): ...@@ -77,7 +79,7 @@ class WheelBuilder(Builder):
wheel_path.unlink() wheel_path.unlink()
shutil.move(temp_path, str(wheel_path)) shutil.move(temp_path, str(wheel_path))
self._io.writeln(" - Built <fg=cyan>{}</>".format(self.wheel_filename)) self._io.write_line(" - Built <fg=cyan>{}</>".format(self.wheel_filename))
def _build(self, wheel): def _build(self, wheel):
if self._package.build: if self._package.build:
...@@ -113,9 +115,8 @@ class WheelBuilder(Builder): ...@@ -113,9 +115,8 @@ class WheelBuilder(Builder):
if rel_path in wheel.namelist(): if rel_path in wheel.namelist():
continue continue
self._io.writeln( self._io.write_line(
" - Adding: <comment>{}</comment>".format(rel_path), " - Adding: <comment>{}</comment>".format(rel_path), VERY_VERBOSE
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
) )
self._add_file(wheel, pkg, rel_path) self._add_file(wheel, pkg, rel_path)
...@@ -149,9 +150,8 @@ class WheelBuilder(Builder): ...@@ -149,9 +150,8 @@ class WheelBuilder(Builder):
# Skip duplicates # Skip duplicates
continue continue
self._io.writeln( self._io.write_line(
" - Adding: <comment>{}</comment>".format(str(file)), " - Adding: <comment>{}</comment>".format(str(file)), VERY_VERBOSE
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
) )
to_add.append((file, rel_file)) to_add.append((file, rel_file))
......
...@@ -23,7 +23,7 @@ class Publisher: ...@@ -23,7 +23,7 @@ class Publisher:
def publish(self, repository_name, username, password): def publish(self, repository_name, username, password):
if repository_name: if repository_name:
self._io.writeln( self._io.write_line(
"Publishing <info>{}</info> (<comment>{}</comment>) " "Publishing <info>{}</info> (<comment>{}</comment>) "
"to <fg=cyan>{}</>".format( "to <fg=cyan>{}</>".format(
self._package.pretty_name, self._package.pretty_name,
...@@ -32,7 +32,7 @@ class Publisher: ...@@ -32,7 +32,7 @@ class Publisher:
) )
) )
else: else:
self._io.writeln( self._io.write_line(
"Publishing <info>{}</info> (<comment>{}</comment>) " "Publishing <info>{}</info> (<comment>{}</comment>) "
"to <fg=cyan>PyPI</>".format( "to <fg=cyan>PyPI</>".format(
self._package.pretty_name, self._package.pretty_version self._package.pretty_name, self._package.pretty_version
......
...@@ -213,7 +213,7 @@ class Uploader: ...@@ -213,7 +213,7 @@ class Uploader:
("content", (file.name, fp, "application/octet-stream")) ("content", (file.name, fp, "application/octet-stream"))
) )
encoder = MultipartEncoder(data_to_send) encoder = MultipartEncoder(data_to_send)
bar = self._io.create_progress_bar(encoder.len) bar = self._io.progress_bar(encoder.len)
bar.set_format( bar.set_format(
" - Uploading <info>{0}</> <comment>%percent%%</>".format(file.name) " - Uploading <info>{0}</> <comment>%percent%%</>".format(file.name)
) )
...@@ -233,7 +233,7 @@ class Uploader: ...@@ -233,7 +233,7 @@ class Uploader:
if resp.ok: if resp.ok:
bar.finish() bar.finish()
self._io.writeln("") self._io.write_line("")
else: else:
self._io.overwrite("") self._io.overwrite("")
......
...@@ -3,16 +3,13 @@ import logging ...@@ -3,16 +3,13 @@ import logging
import os import os
import pkginfo import pkginfo
import re import re
import shutil
import time import time
from cleo import ProgressIndicator from clikit.ui.components import ProgressIndicator
from contextlib import contextmanager from contextlib import contextmanager
from tempfile import mkdtemp from tempfile import mkdtemp
from typing import List from typing import List
from poetry.io import NullIO
from poetry.packages import Dependency from poetry.packages import Dependency
from poetry.packages import DependencyPackage from poetry.packages import DependencyPackage
from poetry.packages import DirectoryDependency from poetry.packages import DirectoryDependency
...@@ -46,20 +43,8 @@ logger = logging.getLogger(__name__) ...@@ -46,20 +43,8 @@ logger = logging.getLogger(__name__)
class Indicator(ProgressIndicator): class Indicator(ProgressIndicator):
def __init__(self, output):
super(Indicator, self).__init__(output)
self.format = "%message% <fg=black;options=bold>(%elapsed:2s%)</>"
@contextmanager
def auto(self):
message = "<info>Resolving dependencies</info>..."
with super(Indicator, self).auto(message, message):
yield
def _formatter_elapsed(self): def _formatter_elapsed(self):
elapsed = time.time() - self.start_time elapsed = time.time() - self._start_time
return "{:.1f}s".format(elapsed) return "{:.1f}s".format(elapsed)
...@@ -625,14 +610,8 @@ class Provider: ...@@ -625,14 +610,8 @@ class Provider:
return package return package
# UI
@property
def output(self):
return self._io
def debug(self, message, depth=0): def debug(self, message, depth=0):
if not (self.output.is_very_verbose() or self.output.is_debug()): if not (self._io.is_very_verbose() or self._io.is_debug()):
return return
if message.startswith("fact:"): if message.startswith("fact:"):
...@@ -717,17 +696,22 @@ class Provider: ...@@ -717,17 +696,22 @@ class Provider:
+ "\n" + "\n"
) )
self.output.write(debug_info) self._io.write(debug_info)
@contextmanager @contextmanager
def progress(self): def progress(self):
if not self._io.is_decorated() or self.is_debugging(): if not self._io.output.supports_ansi() or self.is_debugging():
self.output.writeln("Resolving dependencies...") self._io.write_line("Resolving dependencies...")
yield yield
else: else:
indicator = Indicator(self._io) indicator = Indicator(
self._io, "{message} <fg=black;options=bold>({elapsed:2s})</>"
)
with indicator.auto(): with indicator.auto(
"<info>Resolving dependencies...</info>",
"<info>Resolving dependencies...</info>",
):
yield yield
self._in_progress = False self._in_progress = False
...@@ -13,6 +13,8 @@ from typing import Dict ...@@ -13,6 +13,8 @@ from typing import Dict
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
from clikit.api.io import IO
from poetry.config import Config from poetry.config import Config
from poetry.locations import CACHE_DIR from poetry.locations import CACHE_DIR
from poetry.utils._compat import Path from poetry.utils._compat import Path
...@@ -235,7 +237,7 @@ class Env(object): ...@@ -235,7 +237,7 @@ class Env(object):
if not venv.exists(): if not venv.exists():
if create_venv is False: if create_venv is False:
io.writeln( io.write_line(
"<fg=black;bg=yellow>" "<fg=black;bg=yellow>"
"Skipping virtualenv creation, " "Skipping virtualenv creation, "
"as specified in config file." "as specified in config file."
...@@ -244,14 +246,14 @@ class Env(object): ...@@ -244,14 +246,14 @@ class Env(object):
return SystemEnv(Path(sys.prefix)) return SystemEnv(Path(sys.prefix))
io.writeln( io.write_line(
"Creating virtualenv <info>{}</> in {}".format(name, str(venv_path)) "Creating virtualenv <info>{}</> in {}".format(name, str(venv_path))
) )
cls.build_venv(str(venv)) cls.build_venv(str(venv))
else: else:
if io.is_very_verbose(): if io.is_very_verbose():
io.writeln("Virtualenv <info>{}</> already exists.".format(name)) io.write_line("Virtualenv <info>{}</> already exists.".format(name))
# venv detection: # venv detection:
# stdlib venv may symlink sys.executable, so we can't use realpath. # stdlib venv may symlink sys.executable, so we can't use realpath.
...@@ -528,11 +530,17 @@ class NullEnv(SystemEnv): ...@@ -528,11 +530,17 @@ class NullEnv(SystemEnv):
self._execute = execute self._execute = execute
self.executed = [] self.executed = []
def run(self, bin, *args): def run(self, bin, *args, **kwargs):
self.executed.append([bin] + list(args))
if self._execute:
return super(NullEnv, self).run(bin, *args, **kwargs)
def execute(self, bin, *args, **kwargs):
self.executed.append([bin] + list(args)) self.executed.append([bin] + list(args))
if self._execute: if self._execute:
return super(NullEnv, self).run(bin, *args) return super(NullEnv, self).execute(bin, *args, **kwargs)
def _bin(self, bin): def _bin(self, bin):
return bin return bin
......
...@@ -23,7 +23,7 @@ classifiers = [ ...@@ -23,7 +23,7 @@ classifiers = [
# Requirements # Requirements
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "~2.7 || ^3.4" python = "~2.7 || ^3.4"
cleo = "^0.6.7" cleo = "^0.7.2"
requests = "^2.18" requests = "^2.18"
cachy = "^0.2" cachy = "^0.2"
requests-toolbelt = "^0.8.0" requests-toolbelt = "^0.8.0"
......
...@@ -18,7 +18,7 @@ class MakeReleaseCommand(Command): ...@@ -18,7 +18,7 @@ class MakeReleaseCommand(Command):
""" """
Makes a self-contained package of Poetry. Makes a self-contained package of Poetry.
make:release release
{--P|python=?* : Python version to use} {--P|python=?* : Python version to use}
""" """
...@@ -198,9 +198,22 @@ class MakeReleaseCommand(Command): ...@@ -198,9 +198,22 @@ class MakeReleaseCommand(Command):
self.line("") self.line("")
app = Application("Sonnet") class MakeCommand(Command):
"""
Build poetry releases.
make
"""
commands = [MakeReleaseCommand()]
def handle(self):
return self.call("help", self.config.name)
app = Application("sonnet")
app.add(MakeReleaseCommand()) app.add(MakeCommand())
if __name__ == "__main__": if __name__ == "__main__":
app.run() app.run()
...@@ -4,7 +4,7 @@ from tests.helpers import get_package ...@@ -4,7 +4,7 @@ from tests.helpers import get_package
def test_debug_resolve_gives_resolution_results(app, repo): def test_debug_resolve_gives_resolution_results(app, repo):
command = app.find("debug:resolve") command = app.find("debug resolve")
tester = CommandTester(command) tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0") cachy2 = get_package("cachy", "0.2.0")
...@@ -14,7 +14,7 @@ def test_debug_resolve_gives_resolution_results(app, repo): ...@@ -14,7 +14,7 @@ def test_debug_resolve_gives_resolution_results(app, repo):
repo.add_package(cachy2) repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3")) repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute([("command", command.get_name()), ("package", ["cachy"])]) tester.execute("cachy")
expected = """\ expected = """\
Resolving dependencies... Resolving dependencies...
...@@ -25,11 +25,11 @@ Resolution results: ...@@ -25,11 +25,11 @@ Resolution results:
- cachy (0.2.0) - cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo): def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo):
command = app.find("debug:resolve") command = app.find("debug resolve")
tester = CommandTester(command) tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0") cachy2 = get_package("cachy", "0.2.0")
...@@ -39,9 +39,7 @@ def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo): ...@@ -39,9 +39,7 @@ def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo):
repo.add_package(cachy2) repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3")) repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute( tester.execute("cachy --tree")
[("command", command.get_name()), ("package", ["cachy"]), ("--tree", True)]
)
expected = """\ expected = """\
Resolving dependencies... Resolving dependencies...
...@@ -52,22 +50,17 @@ cachy 0.2.0 ...@@ -52,22 +50,17 @@ cachy 0.2.0
`-- msgpack-python >=0.5 <0.6 `-- msgpack-python >=0.5 <0.6
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_debug_resolve_git_dependency(app, repo): def test_debug_resolve_git_dependency(app, repo):
repo.add_package(get_package("pendulum", "2.0.3")) repo.add_package(get_package("pendulum", "2.0.3"))
repo.add_package(get_package("cleo", "0.6.5")) repo.add_package(get_package("cleo", "0.6.5"))
command = app.find("debug:resolve") command = app.find("debug resolve")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute( tester.execute("git+https://github.com/demo/demo.git")
[
("command", command.get_name()),
("package", ["git+https://github.com/demo/demo.git"]),
]
)
expected = """\ expected = """\
Resolving dependencies... Resolving dependencies...
...@@ -78,4 +71,4 @@ Resolution results: ...@@ -78,4 +71,4 @@ Resolution results:
- demo (0.1.2) - demo (0.1.2)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
...@@ -5,14 +5,13 @@ def test_about(app): ...@@ -5,14 +5,13 @@ def test_about(app):
command = app.find("about") command = app.find("about")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", command.get_name())]) tester.execute()
expected = """\ expected = """\
Poetry - Package Management for Python Poetry - Package Management for Python
Poetry is a dependency manager tracking local dependencies of your projects and libraries. Poetry is a dependency manager tracking local dependencies of your projects and libraries.
See https://github.com/sdispater/poetry for more information. See https://github.com/sdispater/poetry for more information.
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
...@@ -13,7 +13,7 @@ def test_add_no_constraint(app, repo, installer): ...@@ -13,7 +13,7 @@ def test_add_no_constraint(app, repo, installer):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0")) repo.add_package(get_package("cachy", "0.2.0"))
tester.execute([("command", command.get_name()), ("name", ["cachy"])]) tester.execute("cachy")
expected = """\ expected = """\
Using version ^0.2.0 for cachy Using version ^0.2.0 for cachy
...@@ -29,7 +29,7 @@ Writing lock file ...@@ -29,7 +29,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
...@@ -46,7 +46,7 @@ def test_add_constraint(app, repo, installer): ...@@ -46,7 +46,7 @@ def test_add_constraint(app, repo, installer):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0")) repo.add_package(get_package("cachy", "0.2.0"))
tester.execute([("command", command.get_name()), ("name", ["cachy=0.1.0"])]) tester.execute("cachy=0.1.0")
expected = """\ expected = """\
...@@ -61,7 +61,7 @@ Writing lock file ...@@ -61,7 +61,7 @@ Writing lock file
- Installing cachy (0.1.0) - Installing cachy (0.1.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
...@@ -78,7 +78,7 @@ def test_add_constraint_dependencies(app, repo, installer): ...@@ -78,7 +78,7 @@ def test_add_constraint_dependencies(app, repo, installer):
repo.add_package(cachy2) repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3")) repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute([("command", command.get_name()), ("name", ["cachy=0.2.0"])]) tester.execute("cachy=0.2.0")
expected = """\ expected = """\
...@@ -94,7 +94,7 @@ Writing lock file ...@@ -94,7 +94,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -106,13 +106,7 @@ def test_add_git_constraint(app, repo, installer): ...@@ -106,13 +106,7 @@ def test_add_git_constraint(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5")) repo.add_package(get_package("cleo", "0.6.5"))
tester.execute( tester.execute("demo --git https://github.com/demo/demo.git")
[
("command", command.get_name()),
("name", ["demo"]),
("--git", "https://github.com/demo/demo.git"),
]
)
expected = """\ expected = """\
...@@ -128,7 +122,7 @@ Writing lock file ...@@ -128,7 +122,7 @@ Writing lock file
- Installing demo (0.1.2 9cf87a2) - Installing demo (0.1.2 9cf87a2)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -146,13 +140,7 @@ def test_add_git_constraint_with_poetry(app, repo, installer): ...@@ -146,13 +140,7 @@ def test_add_git_constraint_with_poetry(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute( tester.execute("demo --git https://github.com/demo/pyproject-demo.git")
[
("command", command.get_name()),
("name", ["demo"]),
("--git", "https://github.com/demo/pyproject-demo.git"),
]
)
expected = """\ expected = """\
...@@ -168,7 +156,7 @@ Writing lock file ...@@ -168,7 +156,7 @@ Writing lock file
- Installing demo (0.1.2 9cf87a2) - Installing demo (0.1.2 9cf87a2)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -179,13 +167,7 @@ def test_add_file_constraint_wheel(app, repo, installer): ...@@ -179,13 +167,7 @@ def test_add_file_constraint_wheel(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute( tester.execute("demo --path ../distributions/demo-0.1.0-py2.py3-none-any.whl")
[
("command", command.get_name()),
("name", ["demo"]),
("--path", "../distributions/demo-0.1.0-py2.py3-none-any.whl"),
]
)
expected = """\ expected = """\
...@@ -201,7 +183,7 @@ Writing lock file ...@@ -201,7 +183,7 @@ Writing lock file
- Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl) - Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -219,13 +201,7 @@ def test_add_file_constraint_sdist(app, repo, installer): ...@@ -219,13 +201,7 @@ def test_add_file_constraint_sdist(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute( tester.execute("demo --path ../distributions/demo-0.1.0.tar.gz")
[
("command", command.get_name()),
("name", ["demo"]),
("--path", "../distributions/demo-0.1.0.tar.gz"),
]
)
expected = """\ expected = """\
...@@ -241,7 +217,7 @@ Writing lock file ...@@ -241,7 +217,7 @@ Writing lock file
- Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz) - Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -266,13 +242,7 @@ def test_add_constraint_with_extras(app, repo, installer): ...@@ -266,13 +242,7 @@ def test_add_constraint_with_extras(app, repo, installer):
repo.add_package(cachy2) repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3")) repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute( tester.execute("cachy=0.2.0 --extras msgpack")
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--extras", ["msgpack"]),
]
)
expected = """\ expected = """\
...@@ -288,7 +258,7 @@ Writing lock file ...@@ -288,7 +258,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2 assert len(installer.installs) == 2
...@@ -310,13 +280,7 @@ def test_add_constraint_with_python(app, repo, installer): ...@@ -310,13 +280,7 @@ def test_add_constraint_with_python(app, repo, installer):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2) repo.add_package(cachy2)
tester.execute( tester.execute("cachy=0.2.0 --python >=2.7")
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--python", ">=2.7"),
]
)
expected = """\ expected = """\
...@@ -331,7 +295,7 @@ Writing lock file ...@@ -331,7 +295,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
...@@ -351,13 +315,7 @@ def test_add_constraint_with_platform(app, repo, installer): ...@@ -351,13 +315,7 @@ def test_add_constraint_with_platform(app, repo, installer):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2) repo.add_package(cachy2)
tester.execute( tester.execute("cachy=0.2.0 --platform {}".format(platform))
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--platform", platform),
]
)
expected = """\ expected = """\
...@@ -372,7 +330,7 @@ Writing lock file ...@@ -372,7 +330,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
...@@ -392,9 +350,7 @@ def test_add_to_section_that_does_no_exist_yet(app, repo, installer): ...@@ -392,9 +350,7 @@ def test_add_to_section_that_does_no_exist_yet(app, repo, installer):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0")) repo.add_package(get_package("cachy", "0.2.0"))
tester.execute( tester.execute("cachy --dev")
[("command", command.get_name()), ("name", ["cachy"]), ("--dev", True)]
)
expected = """\ expected = """\
Using version ^0.2.0 for cachy Using version ^0.2.0 for cachy
...@@ -410,7 +366,7 @@ Writing lock file ...@@ -410,7 +366,7 @@ Writing lock file
- Installing cachy (0.2.0) - Installing cachy (0.2.0)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
...@@ -427,7 +383,7 @@ def test_add_should_not_select_prereleases(app, repo, installer): ...@@ -427,7 +383,7 @@ def test_add_should_not_select_prereleases(app, repo, installer):
repo.add_package(get_package("pyyaml", "3.13")) repo.add_package(get_package("pyyaml", "3.13"))
repo.add_package(get_package("pyyaml", "4.2b2")) repo.add_package(get_package("pyyaml", "4.2b2"))
tester.execute([("command", command.get_name()), ("name", ["pyyaml"])]) tester.execute("pyyaml")
expected = """\ expected = """\
Using version ^3.13 for pyyaml Using version ^3.13 for pyyaml
...@@ -443,7 +399,7 @@ Writing lock file ...@@ -443,7 +399,7 @@ Writing lock file
- Installing pyyaml (3.13) - Installing pyyaml (3.13)
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1 assert len(installer.installs) == 1
......
...@@ -9,13 +9,13 @@ def test_check_valid(app): ...@@ -9,13 +9,13 @@ def test_check_valid(app):
command = app.find("check") command = app.find("check")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", command.get_name())]) tester.execute()
expected = """\ expected = """\
All set! All set!
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_check_invalid(app): def test_check_invalid(app):
...@@ -25,7 +25,7 @@ def test_check_invalid(app): ...@@ -25,7 +25,7 @@ def test_check_invalid(app):
command = app.find("check") command = app.find("check")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", command.get_name())]) tester.execute()
if PY2: if PY2:
expected = """\ expected = """\
...@@ -40,4 +40,4 @@ Error: INVALID is not a valid license ...@@ -40,4 +40,4 @@ Error: INVALID is not a valid license
Warning: A wildcard Python dependency is ambiguous. Consider specifying a more explicit one. Warning: A wildcard Python dependency is ambiguous. Consider specifying a more explicit one.
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
...@@ -26,10 +26,10 @@ def setup(config): ...@@ -26,10 +26,10 @@ def setup(config):
def test_list_displays_default_value_if_not_set(app, config): def test_list_displays_default_value_if_not_set(app, config):
command = app.find("config") command = app.find("config")
command._config = Config(config.file) command._settings_config = Config(config.file)
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", command.get_name()), ("--list", True)]) tester.execute("--list")
expected = """settings.virtualenvs.create = true expected = """settings.virtualenvs.create = true
settings.virtualenvs.in-project = false settings.virtualenvs.in-project = false
...@@ -37,24 +37,18 @@ settings.virtualenvs.path = "." ...@@ -37,24 +37,18 @@ settings.virtualenvs.path = "."
repositories = {} repositories = {}
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_list_displays_set_get_setting(app, config): def test_list_displays_set_get_setting(app, config):
command = app.find("config") command = app.find("config")
command._config = Config(config.file) command._settings_config = Config(config.file)
tester = CommandTester(command) tester = CommandTester(command)
tester.execute( tester.execute("settings.virtualenvs.create false")
[
("command", command.get_name()),
("key", "settings.virtualenvs.create"),
("value", ["false"]),
]
)
command._config = Config(config.file) command._settings_config = Config(config.file)
tester.execute([("command", command.get_name()), ("--list", True)]) tester.execute("--list")
expected = """settings.virtualenvs.create = false expected = """settings.virtualenvs.create = false
settings.virtualenvs.in-project = false settings.virtualenvs.in-project = false
...@@ -62,19 +56,17 @@ settings.virtualenvs.path = "." ...@@ -62,19 +56,17 @@ settings.virtualenvs.path = "."
repositories = {} repositories = {}
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_display_single_setting(app, config): def test_display_single_setting(app, config):
command = app.find("config") command = app.find("config")
command._config = Config(config.file) command._settings_config = Config(config.file)
tester = CommandTester(command) tester = CommandTester(command)
tester.execute( tester.execute("settings.virtualenvs.create")
[("command", command.get_name()), ("key", "settings.virtualenvs.create")]
)
expected = """true expected = """true
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
...@@ -69,7 +69,7 @@ def test_export_exports_requirements_txt_file_locks_if_no_lock_file(app, repo): ...@@ -69,7 +69,7 @@ def test_export_exports_requirements_txt_file_locks_if_no_lock_file(app, repo):
repo.add_package(get_package("foo", "1.0.0")) repo.add_package(get_package("foo", "1.0.0"))
tester.execute([("command", command.get_name()), ("--format", "requirements.txt")]) tester.execute("--format requirements.txt")
requirements = app.poetry.file.parent / "requirements.txt" requirements = app.poetry.file.parent / "requirements.txt"
assert requirements.exists() assert requirements.exists()
...@@ -84,7 +84,7 @@ foo==1.0.0 ...@@ -84,7 +84,7 @@ foo==1.0.0
""" """
assert expected == content assert expected == content
assert "The lock file does not exist. Locking." in tester.get_display(True) assert "The lock file does not exist. Locking." in tester.io.fetch_output()
def test_export_exports_requirements_txt_uses_lock_file(app, repo): def test_export_exports_requirements_txt_uses_lock_file(app, repo):
...@@ -92,14 +92,14 @@ def test_export_exports_requirements_txt_uses_lock_file(app, repo): ...@@ -92,14 +92,14 @@ def test_export_exports_requirements_txt_uses_lock_file(app, repo):
command = app.find("lock") command = app.find("lock")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", "lock")]) tester.execute()
assert app.poetry.locker.lock.exists() assert app.poetry.locker.lock.exists()
command = app.find("export") command = app.find("export")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", command.get_name()), ("--format", "requirements.txt")]) tester.execute("--format requirements.txt")
requirements = app.poetry.file.parent / "requirements.txt" requirements = app.poetry.file.parent / "requirements.txt"
assert requirements.exists() assert requirements.exists()
...@@ -114,7 +114,7 @@ foo==1.0.0 ...@@ -114,7 +114,7 @@ foo==1.0.0
""" """
assert expected == content assert expected == content
assert "The lock file does not exist. Locking." not in tester.get_display(True) assert "The lock file does not exist. Locking." not in tester.io.fetch_output()
def test_export_fails_on_invalid_format(app, repo): def test_export_fails_on_invalid_format(app, repo):
...@@ -122,7 +122,7 @@ def test_export_fails_on_invalid_format(app, repo): ...@@ -122,7 +122,7 @@ def test_export_fails_on_invalid_format(app, repo):
command = app.find("lock") command = app.find("lock")
tester = CommandTester(command) tester = CommandTester(command)
tester.execute([("command", "lock")]) tester.execute()
assert app.poetry.locker.lock.exists() assert app.poetry.locker.lock.exists()
...@@ -130,4 +130,4 @@ def test_export_fails_on_invalid_format(app, repo): ...@@ -130,4 +130,4 @@ def test_export_fails_on_invalid_format(app, repo):
tester = CommandTester(command) tester = CommandTester(command)
with pytest.raises(ValueError): with pytest.raises(ValueError):
tester.execute([("command", command.get_name()), ("--format", "invalid")]) tester.execute("--format invalid")
...@@ -14,22 +14,19 @@ def test_basic_interactive(app, mocker, poetry): ...@@ -14,22 +14,19 @@ def test_basic_interactive(app, mocker, poetry):
p.return_value = Path(__file__) p.return_value = Path(__file__)
tester = CommandTester(command) tester = CommandTester(command)
tester.set_inputs( inputs = [
[ "my-package", # Package name
"my-package", # Package name "1.2.3", # Version
"1.2.3", # Version "This is a description", # Description
"This is a description", # Description "n", # Author
"n", # Author "MIT", # License
"MIT", # License "~2.7 || ^3.6", # Python
"~2.7 || ^3.6", # Python "n", # Interactive packages
"n", # Interactive packages "n", # Interactive dev packages
"n", # Interactive dev packages "\n", # Generate
"\n", # Generate ]
] tester.execute(inputs="\n".join(inputs))
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
expected = """\ expected = """\
[tool.poetry] [tool.poetry]
name = "my-package" name = "my-package"
...@@ -44,7 +41,7 @@ python = "~2.7 || ^3.6" ...@@ -44,7 +41,7 @@ python = "~2.7 || ^3.6"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
""" """
assert expected in output assert expected in tester.io.fetch_output()
def test_interactive_with_dependencies(app, repo, mocker, poetry): def test_interactive_with_dependencies(app, repo, mocker, poetry):
...@@ -59,30 +56,27 @@ def test_interactive_with_dependencies(app, repo, mocker, poetry): ...@@ -59,30 +56,27 @@ def test_interactive_with_dependencies(app, repo, mocker, poetry):
p.return_value = Path(__file__).parent p.return_value = Path(__file__).parent
tester = CommandTester(command) tester = CommandTester(command)
tester.set_inputs( inputs = [
[ "my-package", # Package name
"my-package", # Package name "1.2.3", # Version
"1.2.3", # Version "This is a description", # Description
"This is a description", # Description "n", # Author
"n", # Author "MIT", # License
"MIT", # License "~2.7 || ^3.6", # Python
"~2.7 || ^3.6", # Python "", # Interactive packages
"", # Interactive packages "pendulum", # Search for package
"pendulum", # Search for package "0", # First option
"0", # First option "", # Do not set constraint
"", # Do not set constraint "", # Stop searching for packages
"", # Stop searching for packages "", # Interactive dev packages
"", # Interactive dev packages "pytest", # Search for package
"pytest", # Search for package "0",
"0", "",
"", "",
"", "\n", # Generate
"\n", # Generate ]
] tester.execute(inputs="\n".join(inputs))
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
expected = """\ expected = """\
[tool.poetry] [tool.poetry]
name = "my-package" name = "my-package"
...@@ -99,7 +93,7 @@ pendulum = "^2.0" ...@@ -99,7 +93,7 @@ pendulum = "^2.0"
pytest = "^3.6" pytest = "^3.6"
""" """
assert expected in output assert expected in tester.io.fetch_output()
def test_empty_license(app, mocker, poetry): def test_empty_license(app, mocker, poetry):
...@@ -111,22 +105,19 @@ def test_empty_license(app, mocker, poetry): ...@@ -111,22 +105,19 @@ def test_empty_license(app, mocker, poetry):
p.return_value = Path(__file__) p.return_value = Path(__file__)
tester = CommandTester(command) tester = CommandTester(command)
tester.set_inputs( inputs = [
[ "my-package", # Package name
"my-package", # Package name "1.2.3", # Version
"1.2.3", # Version "", # Description
"", # Description "n", # Author
"n", # Author "", # License
"", # License "", # Python
"", # Python "n", # Interactive packages
"n", # Interactive packages "n", # Interactive dev packages
"n", # Interactive dev packages "\n", # Generate
"\n", # Generate ]
] tester.execute(inputs="\n".join(inputs))
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
expected = """\ expected = """\
[tool.poetry] [tool.poetry]
name = "my-package" name = "my-package"
...@@ -140,4 +131,4 @@ python = "^3.7" ...@@ -140,4 +131,4 @@ python = "^3.7"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
""" """
assert expected in output assert expected in tester.io.fetch_output()
from cleo.testers import CommandTester
from poetry.utils.env import MockEnv
def test_run_passes_all_args(app, mocker):
env = MockEnv(is_venv=True)
mocker.patch("poetry.utils.env.Env.get", return_value=env)
command = app.find("run")
tester = CommandTester(command)
tester.execute("python -V")
assert [["python", "-V"]] == env.executed
...@@ -65,7 +65,7 @@ def test_show_basic_with_installed_packages(app, poetry, installed): ...@@ -65,7 +65,7 @@ def test_show_basic_with_installed_packages(app, poetry, installed):
} }
) )
tester.execute([("command", command.get_name())]) tester.execute()
expected = """\ expected = """\
cachy 0.1.0 Cachy package cachy 0.1.0 Cachy package
...@@ -73,7 +73,7 @@ pendulum 2.0.0 Pendulum package ...@@ -73,7 +73,7 @@ pendulum 2.0.0 Pendulum package
pytest 3.7.3 Pytest package pytest 3.7.3 Pytest package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_basic_with_not_installed_packages_non_decorated(app, poetry, installed): def test_show_basic_with_not_installed_packages_non_decorated(app, poetry, installed):
...@@ -120,14 +120,14 @@ def test_show_basic_with_not_installed_packages_non_decorated(app, poetry, insta ...@@ -120,14 +120,14 @@ def test_show_basic_with_not_installed_packages_non_decorated(app, poetry, insta
} }
) )
tester.execute([("command", command.get_name())]) tester.execute()
expected = """\ expected = """\
cachy 0.1.0 Cachy package cachy 0.1.0 Cachy package
pendulum (!) 2.0.0 Pendulum package pendulum (!) 2.0.0 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_basic_with_not_installed_packages_decorated(app, poetry, installed): def test_show_basic_with_not_installed_packages_decorated(app, poetry, installed):
...@@ -174,14 +174,14 @@ def test_show_basic_with_not_installed_packages_decorated(app, poetry, installed ...@@ -174,14 +174,14 @@ def test_show_basic_with_not_installed_packages_decorated(app, poetry, installed
} }
) )
tester.execute([("command", command.get_name())], {"decorated": True}) tester.execute(decorated=True)
expected = """\ expected = """\
\033[32mcachy \033[0m \033[36m0.1.0\033[0m Cachy package \033[32mcachy \033[0m \033[36m0.1.0\033[0m Cachy package
\033[31mpendulum\033[0m \033[36m2.0.0\033[0m Pendulum package \033[31mpendulum\033[0m \033[36m2.0.0\033[0m Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_latest_non_decorated(app, poetry, installed, repo): def test_show_latest_non_decorated(app, poetry, installed, repo):
...@@ -239,14 +239,14 @@ def test_show_latest_non_decorated(app, poetry, installed, repo): ...@@ -239,14 +239,14 @@ def test_show_latest_non_decorated(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--latest", True)]) tester.execute("--latest")
expected = """\ expected = """\
cachy 0.1.0 0.2.0 Cachy package cachy 0.1.0 0.2.0 Cachy package
pendulum 2.0.0 2.0.1 Pendulum package pendulum 2.0.0 2.0.1 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_latest_decorated(app, poetry, installed, repo): def test_show_latest_decorated(app, poetry, installed, repo):
...@@ -304,16 +304,14 @@ def test_show_latest_decorated(app, poetry, installed, repo): ...@@ -304,16 +304,14 @@ def test_show_latest_decorated(app, poetry, installed, repo):
} }
) )
tester.execute( tester.execute("--latest", decorated=True)
[("command", command.get_name()), ("--latest", True)], {"decorated": True}
)
expected = """\ expected = """\
\033[32mcachy \033[0m \033[36m0.1.0\033[0m \033[33m0.2.0\033[0m Cachy package \033[32mcachy \033[0m \033[36m0.1.0\033[0m \033[33m0.2.0\033[0m Cachy package
\033[32mpendulum\033[0m \033[36m2.0.0\033[0m \033[31m2.0.1\033[0m Pendulum package \033[32mpendulum\033[0m \033[36m2.0.0\033[0m \033[31m2.0.1\033[0m Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_outdated(app, poetry, installed, repo): def test_show_outdated(app, poetry, installed, repo):
...@@ -368,13 +366,13 @@ def test_show_outdated(app, poetry, installed, repo): ...@@ -368,13 +366,13 @@ def test_show_outdated(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--outdated", True)]) tester.execute("--outdated")
expected = """\ expected = """\
cachy 0.1.0 0.2.0 Cachy package cachy 0.1.0 0.2.0 Cachy package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_outdated_formatting(app, poetry, installed, repo): def test_show_outdated_formatting(app, poetry, installed, repo):
...@@ -432,14 +430,14 @@ def test_show_outdated_formatting(app, poetry, installed, repo): ...@@ -432,14 +430,14 @@ def test_show_outdated_formatting(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--outdated", True)]) tester.execute("--outdated")
expected = """\ expected = """\
cachy 0.1.0 0.2.0 Cachy package cachy 0.1.0 0.2.0 Cachy package
pendulum 2.0.0 2.0.1 Pendulum package pendulum 2.0.0 2.0.1 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
@pytest.mark.parametrize("project_directory", ["project_with_local_dependencies"]) @pytest.mark.parametrize("project_directory", ["project_with_local_dependencies"])
...@@ -533,13 +531,13 @@ def test_show_outdated_local_dependencies(app, poetry, installed, repo): ...@@ -533,13 +531,13 @@ def test_show_outdated_local_dependencies(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--outdated", True)]) tester.execute("--outdated")
expected = """\ expected = """\
cachy 0.1.0 0.2.0 cachy 0.1.0 0.2.0
my-package 0.1.1 ../project_with_setup 0.1.2 ../project_with_setup my-package 0.1.1 ../project_with_setup 0.1.2 ../project_with_setup
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
@pytest.mark.parametrize("project_directory", ["project_with_git_dev_dependency"]) @pytest.mark.parametrize("project_directory", ["project_with_git_dev_dependency"])
...@@ -614,14 +612,14 @@ def test_show_outdated_git_dev_dependency(app, poetry, installed, repo): ...@@ -614,14 +612,14 @@ def test_show_outdated_git_dev_dependency(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--outdated", True)]) tester.execute("--outdated")
expected = """\ expected = """\
cachy 0.1.0 0.2.0 Cachy package cachy 0.1.0 0.2.0 Cachy package
demo 0.1.1 9cf87a2 0.1.2 9cf87a2 Demo package demo 0.1.1 9cf87a2 0.1.2 9cf87a2 Demo package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
@pytest.mark.parametrize("project_directory", ["project_with_git_dev_dependency"]) @pytest.mark.parametrize("project_directory", ["project_with_git_dev_dependency"])
...@@ -696,15 +694,13 @@ def test_show_outdated_no_dev_git_dev_dependency(app, poetry, installed, repo): ...@@ -696,15 +694,13 @@ def test_show_outdated_no_dev_git_dev_dependency(app, poetry, installed, repo):
} }
) )
tester.execute( tester.execute("--outdated --no-dev")
[("command", command.get_name()), ("--outdated", True), ("--no-dev", True)]
)
expected = """\ expected = """\
cachy 0.1.0 0.2.0 Cachy package cachy 0.1.0 0.2.0 Cachy package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_hides_incompatible_package(app, poetry, installed, repo): def test_show_hides_incompatible_package(app, poetry, installed, repo):
...@@ -753,13 +749,13 @@ def test_show_hides_incompatible_package(app, poetry, installed, repo): ...@@ -753,13 +749,13 @@ def test_show_hides_incompatible_package(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name())]) tester.execute()
expected = """\ expected = """\
pendulum 2.0.0 Pendulum package pendulum 2.0.0 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_all_shows_incompatible_package(app, poetry, installed, repo): def test_show_all_shows_incompatible_package(app, poetry, installed, repo):
...@@ -808,14 +804,14 @@ def test_show_all_shows_incompatible_package(app, poetry, installed, repo): ...@@ -808,14 +804,14 @@ def test_show_all_shows_incompatible_package(app, poetry, installed, repo):
} }
) )
tester.execute([("command", command.get_name()), ("--all", True)]) tester.execute("--all")
expected = """\ expected = """\
cachy 0.1.0 Cachy package cachy 0.1.0 Cachy package
pendulum 2.0.0 Pendulum package pendulum 2.0.0 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_non_dev_with_basic_installed_packages(app, poetry, installed): def test_show_non_dev_with_basic_installed_packages(app, poetry, installed):
...@@ -879,11 +875,66 @@ def test_show_non_dev_with_basic_installed_packages(app, poetry, installed): ...@@ -879,11 +875,66 @@ def test_show_non_dev_with_basic_installed_packages(app, poetry, installed):
} }
) )
tester.execute([("command", command.get_name()), ("--no-dev", True)]) tester.execute("--no-dev")
expected = """\ expected = """\
cachy 0.1.0 Cachy package cachy 0.1.0 Cachy package
pendulum 2.0.0 Pendulum package pendulum 2.0.0 Pendulum package
""" """
assert tester.get_display(True) == expected assert expected == tester.io.fetch_output()
def test_show_tree(app, poetry, installed):
command = app.find("show")
tester = CommandTester(command)
poetry.package.add_dependency("cachy", "^0.2.0")
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
installed.add_package(cachy2)
poetry.locker.mock_lock_data(
{
"package": [
{
"name": "cachy",
"version": "0.2.0",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
"dependencies": {"msgpack-python": ">=0.5 <0.6"},
},
{
"name": "msgpack-python",
"version": "0.5.1",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
},
],
"metadata": {
"python-versions": "*",
"platform": "*",
"content-hash": "123456789",
"hashes": {"cachy": [], "msgpack-python": []},
},
}
)
tester.execute("--tree")
expected = """\
cachy 0.2.0
`-- msgpack-python >=0.5 <0.6
"""
assert expected == tester.io.fetch_output()
...@@ -4,9 +4,10 @@ import sys ...@@ -4,9 +4,10 @@ import sys
import pytest import pytest
from clikit.io import NullIO
from poetry.installation import Installer as BaseInstaller from poetry.installation import Installer as BaseInstaller
from poetry.installation.noop_installer import NoopInstaller from poetry.installation.noop_installer import NoopInstaller
from poetry.io import NullIO
from poetry.packages import Locker as BaseLocker from poetry.packages import Locker as BaseLocker
from poetry.packages import ProjectPackage from poetry.packages import ProjectPackage
from poetry.repositories import Pool from poetry.repositories import Pool
......
from poetry.io import NullIO from clikit.io import NullIO
from poetry.masonry.builders.builder import Builder from poetry.masonry.builders.builder import Builder
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
......
...@@ -9,8 +9,9 @@ import tarfile ...@@ -9,8 +9,9 @@ import tarfile
import zipfile import zipfile
import tempfile import tempfile
from clikit.io import NullIO
from poetry import __version__ from poetry import __version__
from poetry.io import NullIO
from poetry.masonry.builders import CompleteBuilder from poetry.masonry.builders import CompleteBuilder
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import ast import ast
import pytest import pytest
import re
import shutil import shutil
import tarfile import tarfile
from email.parser import Parser from email.parser import Parser
from poetry.io import NullIO from clikit.io import NullIO
from poetry.masonry.builders.sdist import SdistBuilder from poetry.masonry.builders.sdist import SdistBuilder
from poetry.masonry.utils.package_include import PackageInclude from poetry.masonry.utils.package_include import PackageInclude
from poetry.packages import Package from poetry.packages import Package
......
...@@ -2,7 +2,8 @@ import pytest ...@@ -2,7 +2,8 @@ import pytest
import shutil import shutil
import zipfile import zipfile
from poetry.io import NullIO from clikit.io import NullIO
from poetry.masonry.builders import WheelBuilder from poetry.masonry.builders import WheelBuilder
from poetry.poetry import Poetry from poetry.poetry import Poetry
from poetry.utils._compat import Path from poetry.utils._compat import Path
......
import pytest import pytest
from poetry.io import NullIO from clikit.io import NullIO
from poetry.packages.project_package import ProjectPackage from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Pool from poetry.repositories import Pool
from poetry.repositories import Repository from poetry.repositories import Repository
......
import pytest import pytest
from poetry.io import NullIO from clikit.io import NullIO
from poetry.packages import ProjectPackage from poetry.packages import ProjectPackage
from poetry.packages.directory_dependency import DirectoryDependency from poetry.packages.directory_dependency import DirectoryDependency
from poetry.packages.file_dependency import FileDependency from poetry.packages.file_dependency import FileDependency
......
import pytest import pytest
from cleo.outputs.null_output import NullOutput from clikit.io import NullIO
from cleo.styles import OutputStyle
from poetry.packages import dependency_from_pep_508 from poetry.packages import dependency_from_pep_508
from poetry.packages import ProjectPackage from poetry.packages import ProjectPackage
...@@ -22,7 +21,7 @@ from tests.repositories.test_legacy_repository import ( ...@@ -22,7 +21,7 @@ from tests.repositories.test_legacy_repository import (
@pytest.fixture() @pytest.fixture()
def io(): def io():
return OutputStyle(NullOutput()) return NullIO()
@pytest.fixture() @pytest.fixture()
......
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