diff --git a/poetry.lock b/poetry.lock
index 2bd0b2f81ae..36fd2d14110 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -138,10 +138,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.7.6"
+version = "0.8.0"
[package.dependencies]
-clikit = ">=0.4.0,<0.5.0"
+clikit = ">=0.5.0,<0.6.0"
[[package]]
category = "dev"
@@ -158,7 +158,7 @@ description = "CliKit is a group of utilities to build beautiful and testable co
name = "clikit"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.4.3"
+version = "0.5.1"
[package.dependencies]
pastel = ">=0.2.0,<0.3.0"
@@ -176,6 +176,10 @@ version = ">=3.6,<4.0"
python = ">=3.5.0,<3.5.4"
version = ">=3.6,<4.0"
+[package.dependencies.woops]
+python = ">=3.6,<4.0"
+version = ">=0.2.1,<0.3.0"
+
[[package]]
category = "dev"
description = "Cross-platform colored terminal text."
@@ -1303,6 +1307,15 @@ optional = false
python-versions = "*"
version = "0.5.1"
+[[package]]
+category = "main"
+description = "Handle and manage Python errors with ease"
+marker = "python_version >= \"3.6\" and python_version < \"4.0\""
+name = "woops"
+optional = false
+python-versions = ">=3.6,<4.0"
+version = "0.2.1"
+
[[package]]
category = "main"
description = "Backport of pathlib-compatible object wrapper for zip files"
@@ -1322,7 +1335,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"]
[metadata]
-content-hash = "35617c80a428d8f081214fcbe428540df288e67e5596531cba40415f19438d57"
+content-hash = "7ae766406ba58bc44d4b0d5876927ab0db9005d6a80efab83ddd6a2c50c2f8c8"
python-versions = "~2.7 || ^3.5"
[metadata.files]
@@ -1397,16 +1410,16 @@ chardet = [
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
]
cleo = [
- {file = "cleo-0.7.6-py2.py3-none-any.whl", hash = "sha256:9443d67e5b2da79b32d820ae41758dd6a25618345cb10b9a022a695e26b291b9"},
- {file = "cleo-0.7.6.tar.gz", hash = "sha256:99cf342406f3499cec43270fcfaf93c126c5164092eca201dfef0f623360b409"},
+ {file = "cleo-0.8.0-py2.py3-none-any.whl", hash = "sha256:dcb791b246c02d59ea8eaf05a05d986e547dbe8ba2496ed59048e5d4ab93b537"},
+ {file = "cleo-0.8.0.tar.gz", hash = "sha256:b2d56e93b182358591d0ec46c4f787736378a6a8adf4a6512f72aeb0506de981"},
]
click = [
{file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"},
{file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"},
]
clikit = [
- {file = "clikit-0.4.3-py2.py3-none-any.whl", hash = "sha256:71e321b7795a2a6c4888629f43365d52db071737e668ab16861121d7dd3ada09"},
- {file = "clikit-0.4.3.tar.gz", hash = "sha256:6e2d7e115e7c7b35bceb0209109935ab2f9ab50910e9ff2293f7fa0b7abf973e"},
+ {file = "clikit-0.5.1-py2.py3-none-any.whl", hash = "sha256:f697b6e3125cf4bdc6394184c687f52fe3323152ca6bb99db444201f32904a64"},
+ {file = "clikit-0.5.1.tar.gz", hash = "sha256:2e9cd4c87539d9a0f0275b26e3e50d2d531d7bfbcf4f91909aaa013cfac9d0e1"},
]
colorama = [
{file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
@@ -1896,6 +1909,10 @@ webencodings = [
{file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"},
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
]
+woops = [
+ {file = "woops-0.2.1-py3-none-any.whl", hash = "sha256:77f7179941d0a3d354d923f71428ee2c2519e0b86f465ed5882b98a6d00ec7f0"},
+ {file = "woops-0.2.1.tar.gz", hash = "sha256:f95dee22e055b61980209fdf481f33e743e02d5ef135853c9089d0061370f94a"},
+]
zipp = [
{file = "zipp-1.2.0-py2.py3-none-any.whl", hash = "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"},
{file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"},
diff --git a/poetry/console/commands/build.py b/poetry/console/commands/build.py
index 3d450fb3194..d2473ab0bfd 100644
--- a/poetry/console/commands/build.py
+++ b/poetry/console/commands/build.py
@@ -12,6 +12,11 @@ class BuildCommand(EnvCommand):
option("format", "f", "Limit the format to either sdist or wheel.", flag=False)
]
+ loggers = [
+ "poetry.core.masonry.builders.sdist",
+ "poetry.core.masonry.builders.wheel",
+ ]
+
def handle(self):
from poetry.core.masonry import Builder
@@ -21,7 +26,7 @@ def handle(self):
package = self.poetry.package
self.line(
- "Building {} ({})".format(
+ "Building {} ({})".format(
package.pretty_name, package.version
)
)
diff --git a/poetry/console/commands/install.py b/poetry/console/commands/install.py
index 82585afe96f..8a820c3d585 100644
--- a/poetry/console/commands/install.py
+++ b/poetry/console/commands/install.py
@@ -77,7 +77,7 @@ def handle(self):
return 0
self.line(
- " - Installing {} ({})".format(
+ " - Installing {} ({})".format(
self.poetry.package.pretty_name, self.poetry.package.pretty_version
)
)
diff --git a/poetry/console/config/application_config.py b/poetry/console/config/application_config.py
index 97570956b09..e8f752752fd 100644
--- a/poetry/console/config/application_config.py
+++ b/poetry/console/config/application_config.py
@@ -36,11 +36,12 @@ def configure(self):
super(ApplicationConfig, self).configure()
self.add_style(Style("c1").fg("cyan"))
+ self.add_style(Style("c2").fg("green"))
self.add_style(Style("info").fg("blue"))
self.add_style(Style("comment").fg("green"))
self.add_style(Style("error").fg("red").bold())
- self.add_style(Style("warning").fg("yellow"))
- self.add_style(Style("debug").fg("black").bold())
+ self.add_style(Style("warning").fg("yellow").bold())
+ self.add_style(Style("debug").fg("default").dark())
self.add_event_listener(PRE_HANDLE, self.register_command_loggers)
self.add_event_listener(PRE_HANDLE, self.set_env)
diff --git a/poetry/console/logging/formatters/__init__.py b/poetry/console/logging/formatters/__init__.py
new file mode 100644
index 00000000000..247f51bec8e
--- /dev/null
+++ b/poetry/console/logging/formatters/__init__.py
@@ -0,0 +1,7 @@
+from .builder_formatter import BuilderLogFormatter
+
+
+FORMATTERS = {
+ "poetry.core.masonry.builders.sdist": BuilderLogFormatter(),
+ "poetry.core.masonry.builders.wheel": BuilderLogFormatter(),
+}
diff --git a/poetry/console/logging/formatters/builder_formatter.py b/poetry/console/logging/formatters/builder_formatter.py
new file mode 100644
index 00000000000..df2f7e301fa
--- /dev/null
+++ b/poetry/console/logging/formatters/builder_formatter.py
@@ -0,0 +1,13 @@
+import re
+
+from .formatter import Formatter
+
+
+class BuilderLogFormatter(Formatter):
+ def format(self, msg): # type: (str) -> str
+ if msg.startswith(" - Building ") or msg.startswith(" - Built "):
+ msg = re.sub(r" - (Buil(?:t|ing)) (.+)", " - \\1 \\2", msg)
+ elif msg.startswith(" - Adding: "):
+ msg = re.sub(r" - Adding: (.+)", " - Adding: \\1", msg)
+
+ return msg
diff --git a/poetry/console/logging/formatters/formatter.py b/poetry/console/logging/formatters/formatter.py
new file mode 100644
index 00000000000..35b59374be4
--- /dev/null
+++ b/poetry/console/logging/formatters/formatter.py
@@ -0,0 +1,6 @@
+import logging
+
+
+class Formatter(object):
+ def format(self, record): # type: (logging.LogRecord) -> str
+ raise NotImplementedError()
diff --git a/poetry/console/logging/io_formatter.py b/poetry/console/logging/io_formatter.py
index c9e389a3e4b..9ff57fec761 100644
--- a/poetry/console/logging/io_formatter.py
+++ b/poetry/console/logging/io_formatter.py
@@ -1,5 +1,7 @@
import logging
+from .formatters import FORMATTERS
+
class IOFormatter(logging.Formatter):
@@ -15,7 +17,9 @@ def format(self, record):
level = record.levelname.lower()
msg = record.msg
- if level in self._colors:
+ if record.name in FORMATTERS:
+ msg = FORMATTERS[record.name].format(msg)
+ elif level in self._colors:
msg = "<{}>{}>".format(self._colors[level], msg)
return msg
diff --git a/poetry/installation/installer.py b/poetry/installation/installer.py
index f506e111949..66cb03373fb 100644
--- a/poetry/installation/installer.py
+++ b/poetry/installation/installer.py
@@ -305,7 +305,7 @@ 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.write_line(
- " - Skipping {} ({}) {}".format(
+ " - Skipping {} ({}) {}".format(
operation.package.pretty_name,
operation.package.full_pretty_version,
operation.skip_reason,
@@ -316,7 +316,7 @@ def _execute_install(self, operation): # type: (Install) -> None
if self._execute_operations or self.is_dry_run():
self._io.write_line(
- " - Installing {} ({})".format(
+ " - Installing {} ({})".format(
operation.package.pretty_name, operation.package.full_pretty_version
)
)
@@ -333,7 +333,7 @@ def _execute_update(self, operation): # type: (Update) -> None
if operation.skipped:
if self.is_verbose() and (self._execute_operations or self.is_dry_run()):
self._io.write_line(
- " - Skipping {} ({}) {}".format(
+ " - Skipping {} ({}) {}".format(
target.pretty_name,
target.full_pretty_version,
operation.skip_reason,
@@ -344,7 +344,7 @@ def _execute_update(self, operation): # type: (Update) -> None
if self._execute_operations or self.is_dry_run():
self._io.write_line(
- " - Updating {} ({} -> {})".format(
+ " - Updating {} ({} -> {})".format(
target.pretty_name,
source.full_pretty_version,
target.full_pretty_version,
@@ -360,7 +360,7 @@ 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.write_line(
- " - Not removing {} ({}) {}".format(
+ " - Not removing {} ({}) {}".format(
operation.package.pretty_name,
operation.package.full_pretty_version,
operation.skip_reason,
@@ -371,7 +371,7 @@ def _execute_uninstall(self, operation): # type: (Uninstall) -> None
if self._execute_operations or self.is_dry_run():
self._io.write_line(
- " - Removing {} ({})".format(
+ " - Removing {} ({})".format(
operation.package.pretty_name, operation.package.full_pretty_version
)
)
diff --git a/poetry/publishing/publisher.py b/poetry/publishing/publisher.py
index b62b3addbe6..f1972d78eb7 100644
--- a/poetry/publishing/publisher.py
+++ b/poetry/publishing/publisher.py
@@ -29,7 +29,7 @@ def files(self):
def publish(self, repository_name, username, password, cert=None, client_cert=None):
if repository_name:
self._io.write_line(
- "Publishing {} ({}) "
+ "Publishing {} ({}) "
"to {}".format(
self._package.pretty_name,
self._package.pretty_version,
@@ -38,7 +38,7 @@ def publish(self, repository_name, username, password, cert=None, client_cert=No
)
else:
self._io.write_line(
- "Publishing {} ({}) "
+ "Publishing {} ({}) "
"to PyPI".format(
self._package.pretty_name, self._package.pretty_version
)
diff --git a/poetry/puzzle/provider.py b/poetry/puzzle/provider.py
index fa87f2ef09f..ea42a088c95 100644
--- a/poetry/puzzle/provider.py
+++ b/poetry/puzzle/provider.py
@@ -731,31 +731,31 @@ def debug(self, message, depth=0):
message = (
"fact>: {}{} "
- "depends on {} ({})".format(
+ "depends on {} ({})".format(
name, version, m.group(2), m.group(3)
)
)
elif " is " in message:
message = re.sub(
"fact: (.+) is (.+)",
- "fact>: \\1 is \\2",
+ "fact>: \\1 is \\2",
message,
)
else:
message = re.sub(
- r"(?<=: )(.+?) \((.+?)\)", "\\1 (\\2)", message
+ r"(?<=: )(.+?) \((.+?)\)", "\\1 (\\2)", message
)
message = "fact>: {}".format(message.split("fact: ")[1])
elif message.startswith("selecting "):
message = re.sub(
r"selecting (.+?) \((.+?)\)",
- "selecting> \\1 (\\2)",
+ "selecting> \\1 (\\2)",
message,
)
elif message.startswith("derived:"):
m = re.match(r"derived: (.+?) \((.+?)\)$", message)
if m:
- message = "derived>: {} ({})".format(
+ message = "derived>: {} ({})".format(
m.group(1), m.group(2)
)
else:
@@ -768,14 +768,14 @@ def debug(self, message, depth=0):
m2 = re.match(r"(.+?) \((.+?)\)", m.group(1))
if m2:
name = m2.group(1)
- version = " ({})".format(m2.group(2))
+ version = " ({})".format(m2.group(2))
else:
name = m.group(1)
version = ""
message = (
"conflict>: {}{} "
- "depends on {} ({})".format(
+ "depends on {} ({})".format(
name, version, m.group(2), m.group(3)
)
)
@@ -791,7 +791,7 @@ def debug(self, message, depth=0):
debug_info = (
"\n".join(
[
- "{}:> {}".format(str(depth).rjust(4), s)
+ "{}: {}".format(str(depth).rjust(4), s)
for s in debug_info.split("\n")
]
)
@@ -806,9 +806,7 @@ def progress(self):
self._io.write_line("Resolving dependencies...")
yield
else:
- indicator = Indicator(
- self._io, "{message} ({elapsed:2s})>"
- )
+ indicator = Indicator(self._io, "{message} ({elapsed:2s})")
with indicator.auto(
"Resolving dependencies...",
diff --git a/poetry/repositories/pypi_repository.py b/poetry/repositories/pypi_repository.py
index 76b37daf5bb..e110da77879 100644
--- a/poetry/repositories/pypi_repository.py
+++ b/poetry/repositories/pypi_repository.py
@@ -503,4 +503,4 @@ def _download(self, url, dest): # type: (str, str) -> None
f.write(chunk)
def _log(self, msg, level="info"):
- getattr(logger, level)("{}: {}".format(self._name, msg))
+ getattr(logger, level)("{}: {}".format(self._name, msg))
diff --git a/pyproject.toml b/pyproject.toml
index 2b1940a3f65..2fc42001536 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,8 +24,8 @@ classifiers = [
[tool.poetry.dependencies]
python = "~2.7 || ^3.5"
poetry-core = "^1.0.0a5"
-cleo = "^0.7.6"
-clikit = "^0.4.3"
+cleo = "^0.8.0"
+clikit = "^0.5.1"
requests = "^2.18"
cachy = "^0.3.0"
requests-toolbelt = "^0.8.0"
diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py
index 5415694fa3c..0d9b655dd9e 100644
--- a/tests/console/commands/test_publish.py
+++ b/tests/console/commands/test_publish.py
@@ -1,6 +1,12 @@
+import pytest
+
+from poetry.utils._compat import PY36
from poetry.utils._compat import Path
+@pytest.mark.skipif(
+ not PY36, reason="Improved error rendering is only available on Python >=3.6"
+)
def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http):
http.register_uri(
http.POST, "https://upload.pypi.org/legacy/", status=400, body="Bad Request"
@@ -14,7 +20,34 @@ def test_publish_returns_non_zero_code_for_upload_errors(app, app_tester, http):
Publishing simple-project (1.2.3) to PyPI
-[UploadError]
+ UploadError
+
+ HTTP Error 400: Bad Request
+"""
+
+ assert expected in app_tester.io.fetch_output()
+
+
+@pytest.mark.skipif(
+ PY36, reason="Improved error rendering is not available on Python <3.6"
+)
+def test_publish_returns_non_zero_code_for_upload_errors_older_python(
+ app, app_tester, http
+):
+ http.register_uri(
+ http.POST, "https://upload.pypi.org/legacy/", status=400, body="Bad Request"
+ )
+
+ exit_code = app_tester.execute("publish --username foo --password bar")
+
+ assert 1 == exit_code
+
+ expected = """
+Publishing simple-project (1.2.3) to PyPI
+
+
+UploadError
+
HTTP Error 400: Bad Request
"""