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
......@@ -34,6 +34,11 @@ optional = false
python-versions = "*"
version = "18.2.0"
[package.extras]
dev = ["pre-commit", "zope.interface", "sphinx", "zope.interface", "six", "pytest", "pympler", "hypothesis", "coverage"]
docs = ["zope.interface", "sphinx"]
tests = ["zope.interface", "six", "pytest", "pympler", "hypothesis", "coverage"]
[[package]]
category = "dev"
description = "The uncompromising code formatter."
......@@ -49,6 +54,9 @@ attrs = ">=17.4.0"
click = ">=6.5"
toml = ">=0.9.4"
[package.extras]
d = ["aiohttp (>=3.3.2)"]
[[package]]
category = "main"
description = "httplib2 caching for requests"
......@@ -58,10 +66,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.12.5"
[package.dependencies]
lockfile = ">=0.9"
msgpack = "*"
requests = "*"
[package.dependencies.lockfile]
optional = true
version = ">=0.9"
[package.extras]
filecache = ["lockfile (>=0.9)"]
redis = ["redis (>=2.10.5)"]
[[package]]
category = "dev"
description = "A decorator for caching properties in classes."
......@@ -78,6 +93,11 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.2.0"
[package.extras]
memcached = ["python-memcached (>=1.59.0.0,<2.0.0.0)"]
msgpack = ["msgpack-python (>=0.5.0.0,<0.6.0.0)"]
redis = ["redis (>=2.10.0.0,<3.0.0.0)"]
[[package]]
category = "main"
description = "Python package for providing Mozilla's CA Bundle."
......@@ -111,9 +131,10 @@ description = "Cleo allows you to create beautiful and testable command-line int
name = "cleo"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.6.8"
version = "0.7.2"
[package.dependencies]
clikit = ">=0.2.0,<0.3.0"
pastel = ">=0.1.0,<0.2.0"
pylev = ">=1.3,<2.0"
......@@ -127,6 +148,26 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "7.0"
[[package]]
category = "main"
description = "CliKit is a group of utilities to build beautiful and testable command line interfaces."
name = "clikit"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.2.2"
[package.dependencies]
pastel = ">=0.1.0,<0.2.0"
pylev = ">=1.3,<2.0"
[package.dependencies.enum34]
python = ">=2.7,<2.8"
version = ">=1.1,<2.0"
[package.dependencies.typing]
python = ">=2.7,<2.8 || >=3.4,<3.5"
version = ">=3.6,<4.0"
[[package]]
category = "dev"
description = "Cross-platform colored terminal text."
marker = "sys_platform == \"win32\""
......@@ -199,6 +240,13 @@ version = "1.0.1"
six = ">=1.9"
webencodings = "*"
[package.extras]
all = ["genshi", "chardet (>=2.2)", "datrie", "lxml"]
chardet = ["chardet (>=2.2)"]
datrie = ["datrie"]
genshi = ["genshi"]
lxml = ["lxml"]
[[package]]
category = "dev"
description = "File identification library for Python"
......@@ -262,6 +310,9 @@ version = "2.10"
[package.dependencies]
MarkupSafe = ">=0.23"
[package.extras]
i18n = ["Babel (>=0.8)"]
[[package]]
category = "main"
description = "An implementation of JSON Schema validation for Python"
......@@ -279,6 +330,9 @@ six = ">=1.11.0"
python = "<3"
version = "*"
[package.extras]
format = ["jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"]
[[package]]
category = "dev"
description = "Python LiveReload is an awesome tool for web developers"
......@@ -352,6 +406,10 @@ six = ">=1.9"
python = "<3.3"
version = ">=1"
[package.extras]
docs = ["sphinx", "Pygments (<2)", "jinja2 (<2.7)", "sphinx (<1.3)"]
test = ["unittest2 (>=1.1.0)"]
[[package]]
category = "dev"
description = "More routines for operating on iterables, beyond itertools"
......@@ -432,6 +490,9 @@ optional = false
python-versions = "*"
version = "1.4.2"
[package.extras]
testing = ["nose", "coverage"]
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
......@@ -440,6 +501,9 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.8.0"
[package.extras]
dev = ["tox", "pre-commit"]
[[package]]
category = "dev"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
......@@ -617,6 +681,10 @@ chardet = ">=3.0.2,<3.1.0"
idna = ">=2.5,<2.8"
urllib3 = ">=1.21.1,<1.25"
[package.extras]
security = ["idna (>=2.0.0)", "cryptography (>=1.3.4)", "pyOpenSSL (>=0.14)"]
socks = ["win-inet-pton", "PySocks (>=1.5.6,<1.5.7 || >1.5.7)"]
[[package]]
category = "main"
description = "A utility belt for advanced users of python-requests"
......@@ -716,6 +784,10 @@ six = ">=1.0.0,<2"
toml = ">=0.9.4"
virtualenv = ">=1.11.2"
[package.extras]
docs = ["sphinxcontrib-autoprogram (>=0.1.5)", "pygments-github-lexers (>=0.0.5)", "towncrier (>=18.5.0)", "sphinx (>=1.8.0,<2)"]
testing = ["pytest-randomly (>=1.2.3,<2)", "pytest-xdist (>=1.22.2,<2)", "pytest-timeout (>=1.3.0,<2)", "pytest-mock (>=1.10.0,<2)", "pytest-cov (>=2.5.1,<3)", "pytest (>=3.0.0,<4)"]
[[package]]
category = "main"
description = "Type Hints for Python"
......@@ -733,6 +805,10 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
version = "1.24.1"
[package.extras]
secure = ["ipaddress", "certifi", "idna (>=2.0.0)", "cryptography (>=1.3.4)", "pyOpenSSL (>=0.14)"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
[[package]]
category = "main"
description = "Virtual Python Environment builder"
......@@ -741,6 +817,10 @@ optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "16.1.0"
[package.extras]
docs = ["sphinx (>=1.8.0,<2)"]
testing = ["mock", "pytest-timeout (>=1.3.0,<2)", "coverage (>=4.5.0,<5)", "pytest (>=3.0.0,<4)"]
[[package]]
category = "main"
description = "Character encoding aliases for legacy web content"
......@@ -750,7 +830,7 @@ python-versions = "*"
version = "0.5.1"
[metadata]
content-hash = "cc0af5d7cff3183d13e844efc25bfabc912de0a22eea948614a0895ab4be5ed1"
content-hash = "8618ec2332b366abaf70c871e9afd0f52d410e0cf17c9715525b9157c8874161"
python-versions = "~2.7 || ^3.4"
[metadata.hashes]
......@@ -765,8 +845,9 @@ cachy = ["b71513e5a38ce90c1280c02b7d8d6bb3fdf64666c9cc0584f2479afea097d56c", "b7
certifi = ["339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", "6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"]
cfgv = ["73f48a752bd7aab103c4b882d6596c6360b7aa63b34073dd2c35c7b4b8f93010", "d1791caa9ff5c0c7bce80e7ecc1921752a2eb7c2463a08ed9b6c96b85a2f75aa"]
chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
cleo = ["85a63076b72ca376fb06668be1fc7758dc16740b394783d5cc65200c4b32f71b", "9b7f79f1aa470a025c0d28c76aa225ee9e65028d32f80032e871aa3500df61b8"]
cleo = ["7a5000de616de42fd78f968192651b9174bf333a9079fc9d68ccc672ddfd3624", "a39fa806fd3f64ff0ae4e3a55bb80c8ce60ca73634e13619731d63a04a63be69"]
click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"]
clikit = ["9dbdb3a0f3ddcd2e1851f11b13dc5173d8a4333d627be24e46ddbbc0d83a84e8", "b65cecedfabc2c73865454a57faeca8696408130fc5c2c74df0770335c787bec"]
colorama = ["a3d89af5db9e9806a779a50296b5fdb466e281147c2c235e8225ecc6dbf7bbf3", "c9b54bebe91a6a803e0772c8561d53f2926bfeb17cd141fbabcb08424086595c"]
contextlib2 = ["509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", "f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"]
coverage = ["06123b58a1410873e22134ca2d88bd36680479fe354955b3579fb8ff150e4d27", "09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", "0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", "0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", "0d34245f824cc3140150ab7848d08b7e2ba67ada959d77619c986f2062e1f0e8", "10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", "1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", "1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", "258b21c5cafb0c3768861a6df3ab0cfb4d8b495eee5ec660e16f928bf7385390", "2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", "3ad59c84c502cd134b0088ca9038d100e8fb5081bbd5ccca4863f3804d81f61d", "447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", "46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", "4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", "510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", "5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", "5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", "5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", "6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", "6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", "71afc1f5cd72ab97330126b566bbf4e8661aab7449f08895d21a5d08c6b051ff", "7349c27128334f787ae63ab49d90bf6d47c7288c63a0a5dfaa319d4b4541dd2c", "77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", "828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", "859714036274a75e6e57c7bab0c47a4602d2a8cfaaa33bbdb68c8359b2ed4f5c", "85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", "869ef4a19f6e4c6987e18b315721b8b971f7048e6eaea29c066854242b4e98d9", "8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", "977e2d9a646773cc7428cdd9a34b069d6ee254fadfb4d09b3f430e95472f3cf3", "99bd767c49c775b79fdcd2eabff405f1063d9d959039c0bdd720527a7738748a", "a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", "aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", "ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", "b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", "bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", "c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", "d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", "d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", "da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", "ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", "ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9"]
......
import os
import re
import sys
import traceback
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.io.raw_argv_input import RawArgvInput
from .commands import AboutCommand
from .commands import AddCommand
from .commands import BuildCommand
......@@ -34,22 +25,25 @@ from .commands import ShowCommand
from .commands import UpdateCommand
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.debug import DebugResolveCommand
from .commands.self import SelfCommand
from .commands.self import SelfUpdateCommand
from .config import ApplicationConfig
class Application(BaseApplication):
def __init__(self):
super(Application, self).__init__("Poetry", __version__)
super(Application, self).__init__(
"poetry", __version__, config=ApplicationConfig("poetry", __version__)
)
self._poetry = None
self._skip_io_configuration = False
self._formatter = Formatter(True)
self._formatter.add_style("error", "red", options=["bold"])
for command in self.get_default_commands():
self.add(command)
@property
def poetry(self):
......@@ -65,47 +59,8 @@ class Application(BaseApplication):
def reset_poetry(self): # type: () -> 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
commands = super(Application, self).get_default_commands()
commands += [
commands = [
AboutCommand(),
AddCommand(),
BuildCommand(),
......@@ -129,74 +84,16 @@ class Application(BaseApplication):
]
# Cache commands
commands += [CacheClearCommand()]
commands += [CacheCommand()]
# Debug commands
commands += [DebugInfoCommand(), DebugResolveCommand()]
# Debug command
commands += [DebugCommand()]
# Self commands
commands += [SelfUpdateCommand()]
commands += [SelfCommand()]
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):
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):
from poetry.installation import Installer
......@@ -124,11 +124,7 @@ If you do not specify a version constraint, poetry will choose a suitable one ba
self.reset_poetry()
installer = Installer(
self.output,
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
)
installer.dry_run(self.option("dry-run"))
......
......@@ -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)
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):
"""
Clears poetry's cache.
cache:clear
clear
{ cache : The name of the cache to clear. }
{ --all : Clear all caches. }
"""
......
......@@ -17,7 +17,7 @@ class CheckCommand(Command):
return 0
for error in check_result["errors"]:
self.error("Error: {}".format(error))
self.line("<error>Error: {}</error>".format(error))
for error in check_result["warnings"]:
self.line("<warning>Warning: {}</warning>".format(error))
......
import logging
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):
_loggers = []
loggers = []
@property
def poetry(self):
return self.get_application().poetry
return self.application.poetry
def reset_poetry(self): # type: () -> None
self.get_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)
self.application.reset_poetry()
......@@ -18,7 +18,7 @@ class ConfigCommand(Command):
Sets/Gets config options.
config
{ key : Setting key. }
{ key? : Setting key. }
{ value?* : Setting value. }
{ --list : List configuration settings }
{ --unset : Unset configuration setting }
......@@ -40,7 +40,7 @@ To remove a repository (repo is a short alias for repositories):
super(ConfigCommand, self).__init__()
self._config = Config.create("config.toml")
self._settings_config = Config.create("config.toml")
self._auth_config = Config.create("auth.toml")
@property
......@@ -74,12 +74,10 @@ To remove a repository (repo is a short alias for repositories):
def initialize(self, i, o):
from poetry.utils._compat import decode
super(ConfigCommand, self).initialize(i, o)
# Create config file if it does not exist
if not self._config.file.exists():
self._config.file.parent.mkdir(parents=True, exist_ok=True)
with self._config.file.open("w", encoding="utf-8") as f:
if not self._settings_config.file.exists():
self._settings_config.file.parent.mkdir(parents=True, exist_ok=True)
with self._settings_config.file.open("w", encoding="utf-8") as f:
f.write(decode(TEMPLATE))
if not self._auth_config.file.exists():
......@@ -89,7 +87,7 @@ To remove a repository (repo is a short alias for repositories):
def handle(self):
if self.option("list"):
self._list_configuration(self._config.content)
self._list_configuration(self._settings_config.content)
return 0
......@@ -106,10 +104,12 @@ To remove a repository (repo is a short alias for repositories):
if m:
if not m.group(1):
value = {}
if self._config.setting("repositories") is not None:
value = self._config.setting("repositories")
if self._settings_config.setting("repositories") is not None:
value = self._settings_config.setting("repositories")
else:
repo = self._config.setting("repositories.{}".format(m.group(1)))
repo = self._settings_config.setting(
"repositories.{}".format(m.group(1))
)
if repo is None:
raise ValueError(
"There is no {} repository defined".format(m.group(1))
......@@ -124,7 +124,9 @@ To remove a repository (repo is a short alias for repositories):
raise ValueError("There is no {} setting.".format(setting_key))
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:
......@@ -150,20 +152,26 @@ To remove a repository (repo is a short alias for repositories):
raise ValueError("You cannot remove the [repositories] section")
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:
raise ValueError(
"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
if len(values) == 1:
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
......@@ -222,12 +230,12 @@ To remove a repository (repo is a short alias for repositories):
if not validator(value):
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
def _remove_single_value(self, key):
self._config.remove_property(key)
self._settings_config.remove_property(key)
return 0
......
from .info import DebugInfoCommand
from .resolve import DebugResolveCommand
from .debug import DebugCommand
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):
"""
Shows debug information.
debug:info
info
"""
def handle(self):
......@@ -19,18 +19,17 @@ class DebugInfoCommand(Command):
poetry_python_version = ".".join(str(s) for s in sys.version_info[:3])
self.output.title("Poetry")
self.output.listing(
[
"<info>Version</info>: <comment>{}</>".format(poetry.VERSION),
"<info>Python</info>: <comment>{}</>".format(poetry_python_version),
]
)
self.line("")
self.line("<b>Poetry</b>")
self.line("")
self.line("<info>Version</info>: <comment>{}</>".format(poetry.VERSION))
self.line("<info>Python</info>: <comment>{}</>".format(poetry_python_version))
self.line("")
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 = [
"<info>Python</info>: <comment>{}</>".format(env_python_version),
"<info>Implementation</info>: <comment>{}</>".format(
......@@ -46,17 +45,21 @@ class DebugInfoCommand(Command):
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.output.title("System")
self.output.listing(
[
"<info>Platform</info>: <comment>{}</>".format(sys.platform),
"<info>OS</info>: <comment>{}</>".format(os.name),
"<info>Python</info>: <comment>{}</>".format(env.base),
]
)
self.line("<b>System</b>")
self.line("")
listing = [
"<info>Platform</info>: <comment>{}</>".format(sys.platform),
"<info>OS</info>: <comment>{}</>".format(os.name),
"<info>Python</info>: <comment>{}</>".format(env.base),
]
for line in listing:
self.line(line)
self.line("")
......@@ -9,7 +9,7 @@ class DebugResolveCommand(Command):
"""
Debugs dependency resolution.
debug:resolve
resolve
{ package?* : packages to resolve. }
{ --E|extras=* : Extras to activate for the dependency. }
{ --python= : Python version(s) to use for resolution. }
......@@ -17,7 +17,7 @@ class DebugResolveCommand(Command):
{ --install : Show what would be installed for the current system. }
"""
_loggers = ["poetry.repositories.pypi_repository"]
loggers = ["poetry.repositories.pypi_repository"]
def handle(self):
from poetry.packages import ProjectPackage
......@@ -54,7 +54,7 @@ class DebugResolveCommand(Command):
pool = self.poetry.pool
solver = Solver(package, pool, Repository(), Repository(), self.output)
solver = Solver(package, pool, Repository(), Repository(), self._io)
ops = solver.solve()
......@@ -63,9 +63,8 @@ class DebugResolveCommand(Command):
self.line("")
if self.option("tree"):
show_command = self.get_application().find("show")
show_command.output = self.output
show_command.init_styles()
show_command = self.application.find("show")
show_command.init_styles(self.io)
packages = [op.package for op in ops]
repo = Repository(packages)
......@@ -74,7 +73,7 @@ class DebugResolveCommand(Command):
for pkg in repo.packages:
for require in requires:
if pkg.name == require.name:
show_command.display_package_tree(pkg, repo)
show_command.display_package_tree(self.io, pkg, repo)
break
return 0
......
......@@ -7,35 +7,9 @@ class EnvCommand(Command):
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
def env(self):
return self._env
def set_env(self, env):
self._env = env
......@@ -23,11 +23,11 @@ class ExportCommand(Command):
if not locker.is_locked():
self.line("<comment>The lock file does not exist. Locking.</comment>")
options = []
if self.output.is_debug():
if self.io.is_debug():
options.append(("-vvv", None))
elif self.output.is_very_verbose():
elif self.io.is_very_verbose():
options.append(("-vv", None))
elif self.output.is_verbose():
elif self.io.is_verbose():
options.append(("-v", None))
self.call("lock", options)
......
......@@ -41,18 +41,16 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
from poetry.vcs.git import GitConfig
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
vcs_config = GitConfig()
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")
if not name:
......@@ -86,7 +84,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
question = self.create_question(
"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)
if not author:
......@@ -99,7 +97,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
question = self.create_question(
"License [<comment>{}</comment>]: ".format(license), default=license
)
question.validator = self._validate_license
question.set_validator(self._validate_license)
license = self.ask(question)
current_env = Env.get(Path.cwd())
......@@ -125,6 +123,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
requirements = self._format_requirements(
self._determine_requirements(self.option("dependency"))
)
self.line("")
dev_requirements = {}
......@@ -136,6 +135,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
dev_requirements = self._format_requirements(
self._determine_requirements(self.option("dev-dependency"))
)
self.line("")
layout_ = layout("standard")(
name,
......@@ -149,9 +149,11 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
)
content = layout_.generate_poetry_content()
if self.input.is_interactive():
if self.io.is_interactive():
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):
self.line("<error>Command aborted</error>")
......@@ -203,7 +205,7 @@ The <info>init</info> command creates a basic <comment>pyproject.toml</> file in
constraint = self.ask(question)
if constraint is False:
if constraint is None:
_, constraint = self._find_best_version_for_package(package)
self.line(
......
......@@ -26,19 +26,15 @@ exist it will look for <comment>pyproject.toml</> and do the same.
_loggers = ["poetry.repositories.pypi_repository"]
def handle(self):
from clikit.io import NullIO
from poetry.installation import Installer
from poetry.io import NullIO
from poetry.masonry.builders import SdistBuilder
from poetry.masonry.utils.module import ModuleOrPackageNotFound
from poetry.utils._compat import decode
from poetry.utils.env import NullEnv
installer = Installer(
self.output,
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
)
extras = []
......
......@@ -20,11 +20,7 @@ the current directory, processes it, and locks the depdencies in the <comment>po
from poetry.installation import Installer
installer = Installer(
self.output,
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
)
installer.update(True)
......
......@@ -24,7 +24,7 @@ the config command.
def handle(self):
from poetry.masonry.publishing.publisher import Publisher
publisher = Publisher(self.poetry, self.output)
publisher = Publisher(self.poetry, self.io)
# Building package first, if told
if self.option("build"):
......
......@@ -17,7 +17,7 @@ list of installed packages
<info>poetry remove</info>"""
_loggers = ["poetry.repositories.pypi_repository"]
loggers = ["poetry.repositories.pypi_repository"]
def handle(self):
from poetry.installation import Installer
......@@ -55,11 +55,7 @@ list of installed packages
self.reset_poetry()
installer = Installer(
self.output,
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
)
installer.dry_run(self.option("dry-run"))
......
......@@ -9,6 +9,13 @@ class RunCommand(EnvCommand):
{ 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):
args = self.argument("args")
script = args[0]
......@@ -48,22 +55,5 @@ class RunCommand(EnvCommand):
package = poetry.package
path = poetry.file.parent
module = Module(package.name, path.as_posix(), package.packages)
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
if merge_args:
self._application_definition_merged_with_args = True
return module
......@@ -52,22 +52,5 @@ class ScriptCommand(EnvCommand):
package = poetry.package
path = poetry.file.parent
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
if merge_args:
self._application_definition_merged_with_args = True
return module
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):
"""
Updates poetry to the latest version.
self:update
update
{ version? : The version to update to. }
{ --preview : Install prereleases. }
"""
......@@ -51,7 +51,6 @@ class SelfUpdateCommand(Command):
from poetry.repositories.pypi_repository import PyPiRepository
from poetry.semver import Version
from poetry.utils._compat import Path
from poetry.utils._compat import decode
current = Path(__file__)
try:
......@@ -104,20 +103,7 @@ class SelfUpdateCommand(Command):
self.line("You are using the latest version")
return
try:
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
self.update(release)
def update(self, release):
version = release.version
......
# -*- coding: utf-8 -*-
import sys
from .env_command import EnvCommand
......@@ -24,16 +22,17 @@ lists all packages available."""
colors = ["green", "yellow", "cyan", "magenta", "blue"]
def handle(self):
from clikit.utils.terminal import Terminal
from poetry.repositories.installed_repository import InstalledRepository
from poetry.semver import Version
package = self.argument("package")
if self.option("tree"):
self.init_styles()
self.init_styles(self.io)
if self.option("outdated"):
self.input.set_option("latest", True)
self._args.set_option("latest", True)
include_dev = not self.option("no-dev")
locked_repo = self.poetry.locker.locked_repository(include_dev)
......@@ -45,13 +44,13 @@ lists all packages available."""
for package in packages:
for require in requires:
if package.name == require.name:
self.display_package_tree(package, locked_repo)
self.display_package_tree(self._io, package, locked_repo)
break
return 0
table = self.table(style="compact")
table.get_style().set_vertical_border_char("")
# table.style.line_vc_char = ""
locked_packages = locked_repo.packages
if package:
......@@ -65,7 +64,7 @@ lists all packages available."""
raise ValueError("Package {} not found".format(package))
if self.option("tree"):
self.display_package_tree(pkg, locked_repo)
self.display_package_tree(self.io, pkg, locked_repo)
return 0
......@@ -92,7 +91,7 @@ lists all packages available."""
show_latest = self.option("latest")
show_all = self.option("all")
terminal = self.get_application().terminal
terminal = Terminal()
width = terminal.width
name_length = version_length = latest_length = 0
latest_packages = {}
......@@ -114,7 +113,7 @@ lists all packages available."""
continue
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)
if installed_status == "not-installed":
......@@ -158,7 +157,7 @@ lists all packages available."""
if installed_status == "not-installed":
color = "red"
if not self.output.is_decorated():
if not self._io.output.supports_ansi():
# Non installed in non decorated mode
install_marker = " (!)"
......@@ -200,13 +199,13 @@ lists all packages available."""
self.line(line)
def display_package_tree(self, package, installed_repo):
self.write("<info>{}</info>".format(package.pretty_name))
def display_package_tree(self, io, package, installed_repo):
io.write("<info>{}</info>".format(package.pretty_name))
description = ""
if package.description:
description = " " + package.description
self.line(" {}{}".format(package.pretty_version, description))
io.write_line(" {}{}".format(package.pretty_version, description))
dependencies = package.requires
dependencies = sorted(dependencies, key=lambda x: x.name)
......@@ -226,17 +225,18 @@ lists all packages available."""
name=dependency.name,
constraint=dependency.pretty_constraint,
)
self._write_tree_line(info)
self._write_tree_line(io, info)
tree_bar = tree_bar.replace("└", " ")
packages_in_tree = [package.name, dependency.name]
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(
self,
io,
dependency,
installed_repo,
packages_in_tree,
......@@ -276,7 +276,7 @@ lists all packages available."""
constraint=dependency.pretty_constraint,
warn=circular_warn,
)
self._write_tree_line(info)
self._write_tree_line(io, info)
tree_bar = tree_bar.replace("└", " ")
......@@ -284,24 +284,28 @@ lists all packages available."""
current_tree.append(dependency.name)
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):
if not self.output.is_decorated():
def _write_tree_line(self, io, line):
if not io.output.supports_ansi():
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:
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):
from poetry.io import NullIO
from clikit.io import NullIO
from poetry.puzzle.provider import Provider
from poetry.version.version_selector import VersionSelector
......
......@@ -13,7 +13,7 @@ class UpdateCommand(EnvCommand):
{ --lock : Do not perform install (only update the lockfile). }
"""
_loggers = ["poetry.repositories.pypi_repository"]
loggers = ["poetry.repositories.pypi_repository"]
def handle(self):
from poetry.installation import Installer
......@@ -21,11 +21,7 @@ class UpdateCommand(EnvCommand):
packages = self.argument("packages")
installer = Installer(
self.output,
self.env,
self.poetry.package,
self.poetry.locker,
self.poetry.pool,
self.io, self.env, self.poetry.package, self.poetry.locker, self.poetry.pool
)
if packages:
......
import re
from .command import Command
......@@ -8,7 +6,7 @@ class VersionCommand(Command):
Bumps the version of the project.
version
{ version=patch }
{ version=patch : The version number or the rule to update version }
"""
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 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 Locker
from poetry.packages import Package
from poetry.packages.constraints import parse_constraint as parse_generic_constraint
from poetry.puzzle import Solver
from poetry.puzzle.operations import Install
from poetry.puzzle.operations import Uninstall
......@@ -17,7 +16,6 @@ from poetry.repositories import Pool
from poetry.repositories import Repository
from poetry.repositories.installed_repository import InstalledRepository
from poetry.semver import parse_constraint
from poetry.semver import Version
from poetry.utils.helpers import canonicalize_name
from .base_installer import BaseInstaller
......@@ -27,7 +25,7 @@ from .pip_installer import PipInstaller
class Installer:
def __init__(
self,
io,
io, # type: IO
env,
package, # type: Package
locker, # type: Locker
......@@ -146,7 +144,7 @@ class Installer:
if extra not in self._package.extras:
raise ValueError("Extra [{}] is not specified.".format(extra))
self._io.writeln("<info>Updating dependencies</>")
self._io.write_line("<info>Updating dependencies</>")
solver = Solver(
self._package,
self._pool,
......@@ -157,12 +155,12 @@ class Installer:
ops = solver.solve(use_latest=self._whitelist)
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)
if not self._locker.is_fresh():
self._io.writeln(
self._io.write_line(
"<warning>"
"Warning: The lock file is not up to date with "
"the latest changes in pyproject.toml. "
......@@ -220,12 +218,12 @@ class Installer:
# or optional and not requested, are dropped
self._filter_operations(ops, local_repo)
self._io.new_line()
self._io.write_line("")
# Execute operations
actual_ops = [op for op in ops if not op.skipped]
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):
installs = []
......@@ -253,8 +251,8 @@ class Installer:
elif op.job_type == "uninstall":
uninstalls.append(op.package.pretty_name)
self._io.new_line()
self._io.writeln(
self._io.write_line("")
self._io.write_line(
"Package operations: "
"<info>{}</> install{}, "
"<info>{}</> update{}, "
......@@ -279,10 +277,10 @@ class Installer:
)
if updated_lock:
self._io.writeln("")
self._io.writeln("<info>Writing lock file</>")
self._io.write_line("")
self._io.write_line("<info>Writing lock file</>")
self._io.writeln("")
self._io.write_line("")
for op in ops:
self._execute(op)
......@@ -297,7 +295,7 @@ class Installer:
def _execute_install(self, operation): # type: (Install) -> None
if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.writeln(
self._io.write_line(
" - Skipping <info>{}</> (<comment>{}</>) {}".format(
operation.package.pretty_name,
operation.package.full_pretty_version,
......@@ -308,7 +306,7 @@ class Installer:
return
if self._execute_operations or self.is_dry_run():
self._io.writeln(
self._io.write_line(
" - Installing <info>{}</> (<comment>{}</>)".format(
operation.package.pretty_name, operation.package.full_pretty_version
)
......@@ -325,7 +323,7 @@ class Installer:
if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.writeln(
self._io.write_line(
" - Skipping <info>{}</> (<comment>{}</>) {}".format(
target.pretty_name,
target.full_pretty_version,
......@@ -336,7 +334,7 @@ class Installer:
return
if self._execute_operations or self.is_dry_run():
self._io.writeln(
self._io.write_line(
" - Updating <info>{}</> (<comment>{}</> -> <comment>{}</>)".format(
target.pretty_name,
source.full_pretty_version,
......@@ -352,7 +350,7 @@ class Installer:
def _execute_uninstall(self, operation): # type: (Uninstall) -> None
if operation.skipped:
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(
operation.package.pretty_name,
operation.package.full_pretty_version,
......@@ -363,7 +361,7 @@ class Installer:
return
if self._execute_operations or self.is_dry_run():
self._io.writeln(
self._io.write_line(
" - Removing <info>{}</> (<comment>{}</>)".format(
operation.package.pretty_name, operation.package.full_pretty_version
)
......
import os
import shutil
import tempfile
from subprocess import CalledProcessError
from clikit.io import NullIO
from poetry.config import Config
from poetry.utils.helpers import get_http_basic_auth
from poetry.utils.helpers import safe_rmtree
......@@ -41,7 +42,7 @@ class PipInstaller(BaseInstaller):
if package.source_type == "legacy" and package.source_url:
parsed = urlparse.urlparse(package.source_url)
if parsed.scheme == "http":
self._io.write_error(
self._io.error(
" <warning>Installing from unsecure host: {}</warning>".format(
parsed.hostname
)
......@@ -152,7 +153,6 @@ class PipInstaller(BaseInstaller):
return name
def install_directory(self, package):
from poetry.io import NullIO
from poetry.masonry.builder import SdistBuilder
from poetry.poetry import Poetry
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
import logging
import sys
from clikit.io import NullIO
from poetry.poetry import Poetry
from poetry.io import NullIO
from poetry.utils._compat import Path
from poetry.utils._compat import unicode
from poetry.utils.env import SystemEnv
......
......@@ -8,6 +8,8 @@ from contextlib import contextmanager
from typing import Set
from typing import Union
from clikit.api.io.flags import VERY_VERBOSE
from poetry.utils._compat import Path
from poetry.utils._compat import basestring
from poetry.utils._compat import lru_cache
......@@ -98,26 +100,24 @@ class Builder(object):
# Skip duplicates
continue
self._io.writeln(
" - Adding: <comment>{}</comment>".format(str(file)),
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
self._io.write_line(
" - Adding: <comment>{}</comment>".format(str(file)), VERY_VERBOSE
)
to_add.append(file)
# Include project files
self._io.writeln(
" - Adding: <comment>pyproject.toml</comment>",
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
self._io.write_line(
" - Adding: <comment>pyproject.toml</comment>", VERY_VERBOSE
)
to_add.append(Path("pyproject.toml"))
# If a license file exists, add it
for license_file in self._path.glob("LICENSE*"):
self._io.writeln(
self._io.write_line(
" - Adding: <comment>{}</comment>".format(
license_file.relative_to(self._path)
),
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
VERY_VERBOSE,
)
to_add.append(license_file.relative_to(self._path))
......@@ -126,11 +126,11 @@ class Builder(object):
if "readme" in self._poetry.local_config:
readme = self._path / self._poetry.local_config["readme"]
if readme.exists():
self._io.writeln(
self._io.write_line(
" - Adding: <comment>{}</comment>".format(
readme.relative_to(self._path)
),
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
VERY_VERBOSE,
)
to_add.append(readme.relative_to(self._path))
......
......@@ -17,7 +17,7 @@ class CompleteBuilder(Builder):
sdist_builder = SdistBuilder(self._poetry, self._env, self._io)
sdist_file = sdist_builder.build()
self._io.writeln("")
self._io.write_line("")
dist_dir = self._path / "dist"
with self.unpacked_tarball(sdist_file) as tmpdir:
......
......@@ -54,7 +54,7 @@ Author-email: {author_email}
class SdistBuilder(Builder):
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:
target_dir = self._path / "dist"
......@@ -101,7 +101,7 @@ class SdistBuilder(Builder):
tar.close()
gz.close()
self._io.writeln(" - Built <fg=cyan>{}</>".format(target.name))
self._io.write_line(" - Built <fg=cyan>{}</>".format(target.name))
return target
......
......@@ -13,6 +13,8 @@ from base64 import urlsafe_b64encode
from io import StringIO
from typing import Set
from clikit.api.io.flags import VERY_VERBOSE
from poetry.__version__ import __version__
from poetry.semver import parse_constraint
......@@ -56,7 +58,7 @@ class WheelBuilder(Builder):
cls.make_in(poetry, env, io)
def build(self):
self._io.writeln(" - Building <info>wheel</info>")
self._io.write_line(" - Building <info>wheel</info>")
dist_dir = self._target_dir
if not dist_dir.exists():
......@@ -77,7 +79,7 @@ class WheelBuilder(Builder):
wheel_path.unlink()
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):
if self._package.build:
......@@ -113,9 +115,8 @@ class WheelBuilder(Builder):
if rel_path in wheel.namelist():
continue
self._io.writeln(
" - Adding: <comment>{}</comment>".format(rel_path),
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
self._io.write_line(
" - Adding: <comment>{}</comment>".format(rel_path), VERY_VERBOSE
)
self._add_file(wheel, pkg, rel_path)
......@@ -149,9 +150,8 @@ class WheelBuilder(Builder):
# Skip duplicates
continue
self._io.writeln(
" - Adding: <comment>{}</comment>".format(str(file)),
verbosity=self._io.VERBOSITY_VERY_VERBOSE,
self._io.write_line(
" - Adding: <comment>{}</comment>".format(str(file)), VERY_VERBOSE
)
to_add.append((file, rel_file))
......
......@@ -23,7 +23,7 @@ class Publisher:
def publish(self, repository_name, username, password):
if repository_name:
self._io.writeln(
self._io.write_line(
"Publishing <info>{}</info> (<comment>{}</comment>) "
"to <fg=cyan>{}</>".format(
self._package.pretty_name,
......@@ -32,7 +32,7 @@ class Publisher:
)
)
else:
self._io.writeln(
self._io.write_line(
"Publishing <info>{}</info> (<comment>{}</comment>) "
"to <fg=cyan>PyPI</>".format(
self._package.pretty_name, self._package.pretty_version
......
......@@ -213,7 +213,7 @@ class Uploader:
("content", (file.name, fp, "application/octet-stream"))
)
encoder = MultipartEncoder(data_to_send)
bar = self._io.create_progress_bar(encoder.len)
bar = self._io.progress_bar(encoder.len)
bar.set_format(
" - Uploading <info>{0}</> <comment>%percent%%</>".format(file.name)
)
......@@ -233,7 +233,7 @@ class Uploader:
if resp.ok:
bar.finish()
self._io.writeln("")
self._io.write_line("")
else:
self._io.overwrite("")
......
......@@ -3,16 +3,13 @@ import logging
import os
import pkginfo
import re
import shutil
import time
from cleo import ProgressIndicator
from clikit.ui.components import ProgressIndicator
from contextlib import contextmanager
from tempfile import mkdtemp
from typing import List
from poetry.io import NullIO
from poetry.packages import Dependency
from poetry.packages import DependencyPackage
from poetry.packages import DirectoryDependency
......@@ -46,20 +43,8 @@ logger = logging.getLogger(__name__)
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):
elapsed = time.time() - self.start_time
elapsed = time.time() - self._start_time
return "{:.1f}s".format(elapsed)
......@@ -625,14 +610,8 @@ class Provider:
return package
# UI
@property
def output(self):
return self._io
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
if message.startswith("fact:"):
......@@ -717,17 +696,22 @@ class Provider:
+ "\n"
)
self.output.write(debug_info)
self._io.write(debug_info)
@contextmanager
def progress(self):
if not self._io.is_decorated() or self.is_debugging():
self.output.writeln("Resolving dependencies...")
if not self._io.output.supports_ansi() or self.is_debugging():
self._io.write_line("Resolving dependencies...")
yield
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
self._in_progress = False
......@@ -13,6 +13,8 @@ from typing import Dict
from typing import Optional
from typing import Tuple
from clikit.api.io import IO
from poetry.config import Config
from poetry.locations import CACHE_DIR
from poetry.utils._compat import Path
......@@ -235,7 +237,7 @@ class Env(object):
if not venv.exists():
if create_venv is False:
io.writeln(
io.write_line(
"<fg=black;bg=yellow>"
"Skipping virtualenv creation, "
"as specified in config file."
......@@ -244,14 +246,14 @@ class Env(object):
return SystemEnv(Path(sys.prefix))
io.writeln(
io.write_line(
"Creating virtualenv <info>{}</> in {}".format(name, str(venv_path))
)
cls.build_venv(str(venv))
else:
if io.is_very_verbose():
io.writeln("Virtualenv <info>{}</> already exists.".format(name))
io.write_line("Virtualenv <info>{}</> already exists.".format(name))
# venv detection:
# stdlib venv may symlink sys.executable, so we can't use realpath.
......@@ -528,11 +530,17 @@ class NullEnv(SystemEnv):
self._execute = execute
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))
if self._execute:
return super(NullEnv, self).run(bin, *args)
return super(NullEnv, self).execute(bin, *args, **kwargs)
def _bin(self, bin):
return bin
......
......@@ -23,7 +23,7 @@ classifiers = [
# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
cleo = "^0.6.7"
cleo = "^0.7.2"
requests = "^2.18"
cachy = "^0.2"
requests-toolbelt = "^0.8.0"
......
......@@ -18,7 +18,7 @@ class MakeReleaseCommand(Command):
"""
Makes a self-contained package of Poetry.
make:release
release
{--P|python=?* : Python version to use}
"""
......@@ -198,9 +198,22 @@ class MakeReleaseCommand(Command):
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__":
app.run()
......@@ -4,7 +4,7 @@ from tests.helpers import get_package
def test_debug_resolve_gives_resolution_results(app, repo):
command = app.find("debug:resolve")
command = app.find("debug resolve")
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
......@@ -14,7 +14,7 @@ def test_debug_resolve_gives_resolution_results(app, repo):
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute([("command", command.get_name()), ("package", ["cachy"])])
tester.execute("cachy")
expected = """\
Resolving dependencies...
......@@ -25,11 +25,11 @@ Resolution results:
- 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):
command = app.find("debug:resolve")
command = app.find("debug resolve")
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
......@@ -39,9 +39,7 @@ def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo):
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute(
[("command", command.get_name()), ("package", ["cachy"]), ("--tree", True)]
)
tester.execute("cachy --tree")
expected = """\
Resolving dependencies...
......@@ -52,22 +50,17 @@ cachy 0.2.0
`-- 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):
repo.add_package(get_package("pendulum", "2.0.3"))
repo.add_package(get_package("cleo", "0.6.5"))
command = app.find("debug:resolve")
command = app.find("debug resolve")
tester = CommandTester(command)
tester.execute(
[
("command", command.get_name()),
("package", ["git+https://github.com/demo/demo.git"]),
]
)
tester.execute("git+https://github.com/demo/demo.git")
expected = """\
Resolving dependencies...
......@@ -78,4 +71,4 @@ Resolution results:
- demo (0.1.2)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
......@@ -5,14 +5,13 @@ def test_about(app):
command = app.find("about")
tester = CommandTester(command)
tester.execute([("command", command.get_name())])
tester.execute()
expected = """\
Poetry - Package Management for Python
Poetry is a dependency manager tracking local dependencies of your projects and libraries.
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):
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0"))
tester.execute([("command", command.get_name()), ("name", ["cachy"])])
tester.execute("cachy")
expected = """\
Using version ^0.2.0 for cachy
......@@ -29,7 +29,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......@@ -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.2.0"))
tester.execute([("command", command.get_name()), ("name", ["cachy=0.1.0"])])
tester.execute("cachy=0.1.0")
expected = """\
......@@ -61,7 +61,7 @@ Writing lock file
- Installing cachy (0.1.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......@@ -78,7 +78,7 @@ def test_add_constraint_dependencies(app, repo, installer):
repo.add_package(cachy2)
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 = """\
......@@ -94,7 +94,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2
......@@ -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("cleo", "0.6.5"))
tester.execute(
[
("command", command.get_name()),
("name", ["demo"]),
("--git", "https://github.com/demo/demo.git"),
]
)
tester.execute("demo --git https://github.com/demo/demo.git")
expected = """\
......@@ -128,7 +122,7 @@ Writing lock file
- Installing demo (0.1.2 9cf87a2)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2
......@@ -146,13 +140,7 @@ def test_add_git_constraint_with_poetry(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute(
[
("command", command.get_name()),
("name", ["demo"]),
("--git", "https://github.com/demo/pyproject-demo.git"),
]
)
tester.execute("demo --git https://github.com/demo/pyproject-demo.git")
expected = """\
......@@ -168,7 +156,7 @@ Writing lock file
- Installing demo (0.1.2 9cf87a2)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2
......@@ -179,13 +167,7 @@ def test_add_file_constraint_wheel(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute(
[
("command", command.get_name()),
("name", ["demo"]),
("--path", "../distributions/demo-0.1.0-py2.py3-none-any.whl"),
]
)
tester.execute("demo --path ../distributions/demo-0.1.0-py2.py3-none-any.whl")
expected = """\
......@@ -201,7 +183,7 @@ Writing lock file
- 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
......@@ -219,13 +201,7 @@ def test_add_file_constraint_sdist(app, repo, installer):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute(
[
("command", command.get_name()),
("name", ["demo"]),
("--path", "../distributions/demo-0.1.0.tar.gz"),
]
)
tester.execute("demo --path ../distributions/demo-0.1.0.tar.gz")
expected = """\
......@@ -241,7 +217,7 @@ Writing lock file
- 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
......@@ -266,13 +242,7 @@ def test_add_constraint_with_extras(app, repo, installer):
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute(
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--extras", ["msgpack"]),
]
)
tester.execute("cachy=0.2.0 --extras msgpack")
expected = """\
......@@ -288,7 +258,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 2
......@@ -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(cachy2)
tester.execute(
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--python", ">=2.7"),
]
)
tester.execute("cachy=0.2.0 --python >=2.7")
expected = """\
......@@ -331,7 +295,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......@@ -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(cachy2)
tester.execute(
[
("command", command.get_name()),
("name", ["cachy=0.2.0"]),
("--platform", platform),
]
)
tester.execute("cachy=0.2.0 --platform {}".format(platform))
expected = """\
......@@ -372,7 +330,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......@@ -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.2.0"))
tester.execute(
[("command", command.get_name()), ("name", ["cachy"]), ("--dev", True)]
)
tester.execute("cachy --dev")
expected = """\
Using version ^0.2.0 for cachy
......@@ -410,7 +366,7 @@ Writing lock file
- Installing cachy (0.2.0)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......@@ -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", "4.2b2"))
tester.execute([("command", command.get_name()), ("name", ["pyyaml"])])
tester.execute("pyyaml")
expected = """\
Using version ^3.13 for pyyaml
......@@ -443,7 +399,7 @@ Writing lock file
- Installing pyyaml (3.13)
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
assert len(installer.installs) == 1
......
......@@ -9,13 +9,13 @@ def test_check_valid(app):
command = app.find("check")
tester = CommandTester(command)
tester.execute([("command", command.get_name())])
tester.execute()
expected = """\
All set!
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
def test_check_invalid(app):
......@@ -25,7 +25,7 @@ def test_check_invalid(app):
command = app.find("check")
tester = CommandTester(command)
tester.execute([("command", command.get_name())])
tester.execute()
if PY2:
expected = """\
......@@ -40,4 +40,4 @@ Error: INVALID is not a valid license
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):
def test_list_displays_default_value_if_not_set(app, config):
command = app.find("config")
command._config = Config(config.file)
command._settings_config = Config(config.file)
tester = CommandTester(command)
tester.execute([("command", command.get_name()), ("--list", True)])
tester.execute("--list")
expected = """settings.virtualenvs.create = true
settings.virtualenvs.in-project = false
......@@ -37,24 +37,18 @@ settings.virtualenvs.path = "."
repositories = {}
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
def test_list_displays_set_get_setting(app, config):
command = app.find("config")
command._config = Config(config.file)
command._settings_config = Config(config.file)
tester = CommandTester(command)
tester.execute(
[
("command", command.get_name()),
("key", "settings.virtualenvs.create"),
("value", ["false"]),
]
)
tester.execute("settings.virtualenvs.create false")
command._config = Config(config.file)
tester.execute([("command", command.get_name()), ("--list", True)])
command._settings_config = Config(config.file)
tester.execute("--list")
expected = """settings.virtualenvs.create = false
settings.virtualenvs.in-project = false
......@@ -62,19 +56,17 @@ settings.virtualenvs.path = "."
repositories = {}
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
def test_display_single_setting(app, config):
command = app.find("config")
command._config = Config(config.file)
command._settings_config = Config(config.file)
tester = CommandTester(command)
tester.execute(
[("command", command.get_name()), ("key", "settings.virtualenvs.create")]
)
tester.execute("settings.virtualenvs.create")
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):
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"
assert requirements.exists()
......@@ -84,7 +84,7 @@ foo==1.0.0
"""
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):
......@@ -92,14 +92,14 @@ def test_export_exports_requirements_txt_uses_lock_file(app, repo):
command = app.find("lock")
tester = CommandTester(command)
tester.execute([("command", "lock")])
tester.execute()
assert app.poetry.locker.lock.exists()
command = app.find("export")
tester = CommandTester(command)
tester.execute([("command", command.get_name()), ("--format", "requirements.txt")])
tester.execute("--format requirements.txt")
requirements = app.poetry.file.parent / "requirements.txt"
assert requirements.exists()
......@@ -114,7 +114,7 @@ foo==1.0.0
"""
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):
......@@ -122,7 +122,7 @@ def test_export_fails_on_invalid_format(app, repo):
command = app.find("lock")
tester = CommandTester(command)
tester.execute([("command", "lock")])
tester.execute()
assert app.poetry.locker.lock.exists()
......@@ -130,4 +130,4 @@ def test_export_fails_on_invalid_format(app, repo):
tester = CommandTester(command)
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):
p.return_value = Path(__file__)
tester = CommandTester(command)
tester.set_inputs(
[
"my-package", # Package name
"1.2.3", # Version
"This is a description", # Description
"n", # Author
"MIT", # License
"~2.7 || ^3.6", # Python
"n", # Interactive packages
"n", # Interactive dev packages
"\n", # Generate
]
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
inputs = [
"my-package", # Package name
"1.2.3", # Version
"This is a description", # Description
"n", # Author
"MIT", # License
"~2.7 || ^3.6", # Python
"n", # Interactive packages
"n", # Interactive dev packages
"\n", # Generate
]
tester.execute(inputs="\n".join(inputs))
expected = """\
[tool.poetry]
name = "my-package"
......@@ -44,7 +41,7 @@ python = "~2.7 || ^3.6"
[tool.poetry.dev-dependencies]
"""
assert expected in output
assert expected in tester.io.fetch_output()
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
tester = CommandTester(command)
tester.set_inputs(
[
"my-package", # Package name
"1.2.3", # Version
"This is a description", # Description
"n", # Author
"MIT", # License
"~2.7 || ^3.6", # Python
"", # Interactive packages
"pendulum", # Search for package
"0", # First option
"", # Do not set constraint
"", # Stop searching for packages
"", # Interactive dev packages
"pytest", # Search for package
"0",
"",
"",
"\n", # Generate
]
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
inputs = [
"my-package", # Package name
"1.2.3", # Version
"This is a description", # Description
"n", # Author
"MIT", # License
"~2.7 || ^3.6", # Python
"", # Interactive packages
"pendulum", # Search for package
"0", # First option
"", # Do not set constraint
"", # Stop searching for packages
"", # Interactive dev packages
"pytest", # Search for package
"0",
"",
"",
"\n", # Generate
]
tester.execute(inputs="\n".join(inputs))
expected = """\
[tool.poetry]
name = "my-package"
......@@ -99,7 +93,7 @@ pendulum = "^2.0"
pytest = "^3.6"
"""
assert expected in output
assert expected in tester.io.fetch_output()
def test_empty_license(app, mocker, poetry):
......@@ -111,22 +105,19 @@ def test_empty_license(app, mocker, poetry):
p.return_value = Path(__file__)
tester = CommandTester(command)
tester.set_inputs(
[
"my-package", # Package name
"1.2.3", # Version
"", # Description
"n", # Author
"", # License
"", # Python
"n", # Interactive packages
"n", # Interactive dev packages
"\n", # Generate
]
)
tester.execute([("command", command.name)])
output = tester.get_display(True)
inputs = [
"my-package", # Package name
"1.2.3", # Version
"", # Description
"n", # Author
"", # License
"", # Python
"n", # Interactive packages
"n", # Interactive dev packages
"\n", # Generate
]
tester.execute(inputs="\n".join(inputs))
expected = """\
[tool.poetry]
name = "my-package"
......@@ -140,4 +131,4 @@ python = "^3.7"
[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):
}
)
tester.execute([("command", command.get_name())])
tester.execute()
expected = """\
cachy 0.1.0 Cachy package
......@@ -73,7 +73,7 @@ pendulum 2.0.0 Pendulum 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):
......@@ -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 = """\
cachy 0.1.0 Cachy 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):
......@@ -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 = """\
\033[32mcachy \033[0m \033[36m0.1.0\033[0m Cachy 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):
......@@ -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 = """\
cachy 0.1.0 0.2.0 Cachy 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):
......@@ -304,16 +304,14 @@ def test_show_latest_decorated(app, poetry, installed, repo):
}
)
tester.execute(
[("command", command.get_name()), ("--latest", True)], {"decorated": True}
)
tester.execute("--latest", decorated=True)
expected = """\
\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
"""
assert tester.get_display(True) == expected
assert expected == tester.io.fetch_output()
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 = """\
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):
......@@ -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 = """\
cachy 0.1.0 0.2.0 Cachy 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"])
......@@ -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 = """\
cachy 0.1.0 0.2.0
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"])
......@@ -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 = """\
cachy 0.1.0 0.2.0 Cachy 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"])
......@@ -696,15 +694,13 @@ def test_show_outdated_no_dev_git_dev_dependency(app, poetry, installed, repo):
}
)
tester.execute(
[("command", command.get_name()), ("--outdated", True), ("--no-dev", True)]
)
tester.execute("--outdated --no-dev")
expected = """\
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):
......@@ -753,13 +749,13 @@ def test_show_hides_incompatible_package(app, poetry, installed, repo):
}
)
tester.execute([("command", command.get_name())])
tester.execute()
expected = """\
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):
......@@ -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 = """\
cachy 0.1.0 Cachy 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):
......@@ -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 = """\
cachy 0.1.0 Cachy 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
import pytest
from clikit.io import NullIO
from poetry.installation import Installer as BaseInstaller
from poetry.installation.noop_installer import NoopInstaller
from poetry.io import NullIO
from poetry.packages import Locker as BaseLocker
from poetry.packages import ProjectPackage
from poetry.repositories import Pool
......
from poetry.io import NullIO
from clikit.io import NullIO
from poetry.masonry.builders.builder import Builder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
......
......@@ -9,8 +9,9 @@ import tarfile
import zipfile
import tempfile
from clikit.io import NullIO
from poetry import __version__
from poetry.io import NullIO
from poetry.masonry.builders import CompleteBuilder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
......
# -*- coding: utf-8 -*-
import ast
import pytest
import re
import shutil
import tarfile
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.utils.package_include import PackageInclude
from poetry.packages import Package
......
......@@ -2,7 +2,8 @@ import pytest
import shutil
import zipfile
from poetry.io import NullIO
from clikit.io import NullIO
from poetry.masonry.builders import WheelBuilder
from poetry.poetry import Poetry
from poetry.utils._compat import Path
......
import pytest
from poetry.io import NullIO
from clikit.io import NullIO
from poetry.packages.project_package import ProjectPackage
from poetry.repositories import Pool
from poetry.repositories import Repository
......
import pytest
from poetry.io import NullIO
from clikit.io import NullIO
from poetry.packages import ProjectPackage
from poetry.packages.directory_dependency import DirectoryDependency
from poetry.packages.file_dependency import FileDependency
......
import pytest
from cleo.outputs.null_output import NullOutput
from cleo.styles import OutputStyle
from clikit.io import NullIO
from poetry.packages import dependency_from_pep_508
from poetry.packages import ProjectPackage
......@@ -22,7 +21,7 @@ from tests.repositories.test_legacy_repository import (
@pytest.fixture()
def io():
return OutputStyle(NullOutput())
return NullIO()
@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