From 5a614a568ad0c5b4f958736b161f23746f0df949 Mon Sep 17 00:00:00 2001 From: Luis Martinez de Bartolome Izquierdo Date: Fri, 24 May 2019 13:27:08 +0200 Subject: [PATCH] Exception errors to stderr (#5206) * Exception errors to stderr * Use stderr * Fixed streams * Forced build from source not a warning * Info trace not showing INFO --- conans/client/conan_api.py | 2 +- conans/client/graph/graph_binaries.py | 2 +- conans/client/output.py | 27 ++++++++++++------- conans/client/tools/files.py | 2 +- conans/client/userio.py | 2 +- conans/test/functional/command/build_test.py | 6 ++--- conans/test/functional/command/create_test.py | 8 +++--- .../test/functional/command/install_test.py | 2 +- .../functional/command/test_package_test.py | 4 +-- .../conan_api/two_conan_creates_test.py | 1 + .../test/integration/install_outdated_test.py | 2 +- conans/test/integration/only_source_test.py | 4 +-- conans/tools.py | 2 +- 13 files changed, 36 insertions(+), 28 deletions(-) diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py index 97fe4e9e562..ada65621e49 100644 --- a/conans/client/conan_api.py +++ b/conans/client/conan_api.py @@ -156,7 +156,7 @@ def factory(interactive=None): """Factory""" # Respect color env setting or check tty if unset color = colorama_initialize() - out = ConanOutput(sys.stdout, color) + out = ConanOutput(sys.stdout, sys.stderr, color) user_io = UserIO(out=out) user_home = get_conan_user_home() diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 7f830a38df2..08e06d7960b 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -55,7 +55,7 @@ def _evaluate_node(self, node, build_mode, update, evaluated_nodes, remotes): return if build_mode.forced(conanfile, ref): - output.warn('Forced build from source') + output.info('Forced build from source') node.binary = BINARY_BUILD node.prev = None return diff --git a/conans/client/output.py b/conans/client/output.py index 8136f0d4da6..994f6bb3531 100644 --- a/conans/client/output.py +++ b/conans/client/output.py @@ -61,18 +61,19 @@ class ConanOutput(object): and auxiliary info, success, warn methods for convenience. """ - def __init__(self, stream, color=False): + def __init__(self, stream, stream_err=None, color=False): self._stream = stream + self._stream_err = stream_err or stream self._color = color @property def is_terminal(self): return hasattr(self._stream, "isatty") and self._stream.isatty() - def writeln(self, data, front=None, back=None): - self.write(data, front, back, True) + def writeln(self, data, front=None, back=None, error=False): + self.write(data, front, back, newline=True, error=error) - def write(self, data, front=None, back=None, newline=False): + def write(self, data, front=None, back=None, newline=False, error=False): if six.PY2: if isinstance(data, str): data = decode_text(data) # Keep python 2 compatibility @@ -86,7 +87,10 @@ def write(self, data, front=None, back=None, newline=False): # Windows output locks produce IOErrors for _ in range(3): try: - self._stream.write(data) + if error: + self._stream_err.write(data) + else: + self._stream.write(data) break except IOError: import time @@ -106,10 +110,10 @@ def success(self, data): self.writeln(data, Color.BRIGHT_GREEN) def warn(self, data): - self.writeln("WARN: {}".format(data), Color.BRIGHT_YELLOW) + self.writeln("WARN: {}".format(data), Color.BRIGHT_YELLOW, error=True) def error(self, data): - self.writeln("ERROR: {}".format(data), Color.BRIGHT_RED) + self.writeln("ERROR: {}".format(data), Color.BRIGHT_RED, error=True) def input_text(self, data): self.write(data, Color.GREEN) @@ -133,9 +137,12 @@ class ScopedOutput(ConanOutput): def __init__(self, scope, output): self.scope = scope self._stream = output._stream + self._stream_err = output._stream_err self._color = output._color - def write(self, data, front=None, back=None, newline=False): + def write(self, data, front=None, back=None, newline=False, error=False): assert self.scope != "virtual", "printing with scope==virtual" - super(ScopedOutput, self).write("%s: " % self.scope, front, back, False) - super(ScopedOutput, self).write("%s" % data, Color.BRIGHT_WHITE, back, newline) + super(ScopedOutput, self).write("%s: " % self.scope, front=front, back=back, + newline=False, error=error) + super(ScopedOutput, self).write("%s" % data, front=Color.BRIGHT_WHITE, back=back, + newline=newline, error=error) diff --git a/conans/client/tools/files.py b/conans/client/tools/files.py index 83ae13e5a06..97da6d971b3 100644 --- a/conans/client/tools/files.py +++ b/conans/client/tools/files.py @@ -176,7 +176,7 @@ def patch(base_path=None, patch_file=None, patch_string=None, strip=0, output=No class PatchLogHandler(logging.Handler): def __init__(self): logging.Handler.__init__(self, logging.DEBUG) - self.output = output or ConanOutput(sys.stdout, True) + self.output = output or ConanOutput(sys.stdout, sys.stderr, color=True) self.patchname = patch_file if patch_file else "patch" def emit(self, record): diff --git a/conans/client/userio.py b/conans/client/userio.py index 9bf24343d69..b1bac731702 100644 --- a/conans/client/userio.py +++ b/conans/client/userio.py @@ -19,7 +19,7 @@ def __init__(self, ins=sys.stdin, out=None): """ self._ins = ins if not out: - out = ConanOutput(sys.stdout) + out = ConanOutput(sys.stdout, sys.stderr) self.out = out self._interactive = True diff --git a/conans/test/functional/command/build_test.py b/conans/test/functional/command/build_test.py index 564a52d01cd..3deb1c4f218 100644 --- a/conans/test/functional/command/build_test.py +++ b/conans/test/functional/command/build_test.py @@ -323,7 +323,7 @@ class FooConan(ConanFile): """ client.save({CONANFILE: conanfile}) client.run("create --build foo/1.0@user/stable . user/stable") - self.assertIn("foo/1.0@user/stable: WARN: Forced build from source", client.out) + self.assertIn("foo/1.0@user/stable: Forced build from source", client.out) def build_multiple_full_reference_test(self): client = TestClient() @@ -347,8 +347,8 @@ class BarConan(ConanFile): """ client.save({CONANFILE: conanfile}, clean_first=True) client.run("create --build foo/1.0@user/stable --build bar/1.0@user/testing . user/testing") - self.assertIn("foo/1.0@user/stable: WARN: Forced build from source", client.out) - self.assertIn("bar/1.0@user/testing: WARN: Forced build from source", client.out) + self.assertIn("foo/1.0@user/stable: Forced build from source", client.out) + self.assertIn("bar/1.0@user/testing: Forced build from source", client.out) def debug_build_release_deps_test(self): # https://github.com/conan-io/conan/issues/2899 diff --git a/conans/test/functional/command/create_test.py b/conans/test/functional/command/create_test.py index 537dbf4f474..961d00e5293 100644 --- a/conans/test/functional/command/create_test.py +++ b/conans/test/functional/command/create_test.py @@ -58,13 +58,13 @@ def test(self): ''' client.save({"conanfile.py": conanfile, "test_package/conanfile.py": test_package}) client.run("create . lasote/testing") - self.assertIn("HelloBar/0.1@lasote/testing: WARN: Forced build from source", + self.assertIn("HelloBar/0.1@lasote/testing: Forced build from source", client.user_io.out) client.save({"conanfile.py": conanfile.replace("HelloBar", "Hello") + " requires='HelloBar/0.1@lasote/testing'", "test_package/conanfile.py": test_package.replace("HelloBar", "Hello")}) client.run("create . lasote/stable") - self.assertNotIn("HelloBar/0.1@lasote/testing: WARN: Forced build from source", + self.assertNotIn("HelloBar/0.1@lasote/testing: Forced build from source", client.user_io.out) @parameterized.expand([(True, ), (False, )]) @@ -433,13 +433,13 @@ def test(self): ''' client.save({"conanfile.py": conanfile, "test_package/conanfile.py": test_package}) client.run("create . lasote/testing") - self.assertIn("HelloBar/0.1@lasote/testing: WARN: Forced build from source", + self.assertIn("HelloBar/0.1@lasote/testing: Forced build from source", client.out) client.save({"conanfile.py": conanfile.replace("HelloBar", "Hello") + " requires='HelloBar/0.1@lasote/testing'", "test_package/conanfile.py": test_package.replace("HelloBar", "Hello")}) client.run("create . lasote/stable") - self.assertIn("HelloBar/0.1@lasote/testing: WARN: Forced build from source", + self.assertIn("HelloBar/0.1@lasote/testing: Forced build from source", client.out) def test_build_folder_handling_test(self): diff --git a/conans/test/functional/command/install_test.py b/conans/test/functional/command/install_test.py index a732157f96b..36c91ba619a 100644 --- a/conans/test/functional/command/install_test.py +++ b/conans/test/functional/command/install_test.py @@ -218,7 +218,7 @@ def install_combined_test(self): self.client.run("install . %s --build=missing --build Hello1" % (self.settings)) self.assertIn("Hello0/0.1@lasote/stable: Already installed!", self.client.user_io.out) - self.assertIn("Hello1/0.1@lasote/stable: WARN: Forced build from source", + self.assertIn("Hello1/0.1@lasote/stable: Forced build from source", self.client.user_io.out) def install_transitive_cache_test(self): diff --git a/conans/test/functional/command/test_package_test.py b/conans/test/functional/command/test_package_test.py index c27d8e2ee37..4906b2f3497 100644 --- a/conans/test/functional/command/test_package_test.py +++ b/conans/test/functional/command/test_package_test.py @@ -46,9 +46,9 @@ def test(self): client.run("test test_package Hello/0.1@lasote/stable") self.assertNotIn("Exporting package recipe", client.out) - self.assertNotIn("WARN: Forced build from source", client.out) + self.assertNotIn("Forced build from source", client.out) self.assertNotIn("Package '%s' created" % NO_SETTINGS_PACKAGE_ID, client.out) - self.assertNotIn("WARN: Forced build from source", client.out) + self.assertNotIn("Forced build from source", client.out) self.assertIn("Hello/0.1@lasote/stable: Already installed!", client.out) client.save({"test_package/conanfile.py": test_conanfile}, clean_first=True) diff --git a/conans/test/functional/conan_api/two_conan_creates_test.py b/conans/test/functional/conan_api/two_conan_creates_test.py index c4f578a922a..974769b3a72 100644 --- a/conans/test/functional/conan_api/two_conan_creates_test.py +++ b/conans/test/functional/conan_api/two_conan_creates_test.py @@ -52,6 +52,7 @@ def test_api_conanfile_loader_shouldnt_cache(self): old_stdout = sys.stdout result = StringIO() sys.stdout = result + sys.stderr = sys.stdout api, _, _ = ConanAPIV1.factory() api._user_io.out = TestBufferConanOutput() conanfile = dedent(""" diff --git a/conans/test/integration/install_outdated_test.py b/conans/test/integration/install_outdated_test.py index 25ce4da7dec..264def0775b 100644 --- a/conans/test/integration/install_outdated_test.py +++ b/conans/test/integration/install_outdated_test.py @@ -126,7 +126,7 @@ def install_outdated_and_dep_test(self): # binary is in the "same version" than local cached Hello0 new_client.run("install Hello1/0.1@lasote/stable --build outdated --build Hello1") self.assertIn("Downloading conan_package.tgz", new_client.user_io.out) - self.assertIn("Hello1/0.1@lasote/stable: WARN: Forced build from source", + self.assertIn("Hello1/0.1@lasote/stable: Forced build from source", new_client.user_io.out) def install_outdated_checking_updates_test(self): diff --git a/conans/test/integration/only_source_test.py b/conans/test/integration/only_source_test.py index 27ea09b98fe..17cea4d7465 100644 --- a/conans/test/integration/only_source_test.py +++ b/conans/test/integration/only_source_test.py @@ -65,12 +65,12 @@ def test(self): # Now Hello2 should be built and not fail client.run("create . lasote/stable") self.assertNotIn("Can't find a 'Hello2/2.2@lasote/stable' package", client.user_io.out) - self.assertIn('Hello2/2.2@lasote/stable: WARN: Forced build from source', + self.assertIn('Hello2/2.2@lasote/stable: Forced build from source', client.user_io.out) # Now package is generated but should be built again client.run("create . lasote/stable") - self.assertIn('Hello2/2.2@lasote/stable: WARN: Forced build from source', + self.assertIn('Hello2/2.2@lasote/stable: Forced build from source', client.user_io.out) def build_policies_update_test(self): diff --git a/conans/tools.py b/conans/tools.py index 5647ce86292..c07cc08e15c 100644 --- a/conans/tools.py +++ b/conans/tools.py @@ -52,7 +52,7 @@ def get_global_instances(): # Assign a default, will be overwritten in the factory of the ConanAPI -set_global_instances(the_output=ConanOutput(sys.stdout, True), the_requester=requests) +set_global_instances(the_output=ConanOutput(sys.stdout, sys.stderr, True), the_requester=requests) """