Skip to content

Commit

Permalink
Exception errors to stderr (#5206)
Browse files Browse the repository at this point in the history
* Exception errors to stderr

* Use stderr

* Fixed streams

* Forced build from source not a warning

* Info trace not showing INFO
  • Loading branch information
lasote authored and memsharded committed May 24, 2019
1 parent eab7b6e commit 5a614a5
Show file tree
Hide file tree
Showing 13 changed files with 36 additions and 28 deletions.
2 changes: 1 addition & 1 deletion conans/client/conan_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion conans/client/graph/graph_binaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 17 additions & 10 deletions conans/client/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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)
2 changes: 1 addition & 1 deletion conans/client/tools/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion conans/client/userio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions conans/test/functional/command/build_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions conans/test/functional/command/create_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, )])
Expand Down Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion conans/test/functional/command/install_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
4 changes: 2 additions & 2 deletions conans/test/functional/command/test_package_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions conans/test/functional/conan_api/two_conan_creates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("""
Expand Down
2 changes: 1 addition & 1 deletion conans/test/integration/install_outdated_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
4 changes: 2 additions & 2 deletions conans/test/integration/only_source_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion conans/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


"""
Expand Down

0 comments on commit 5a614a5

Please sign in to comment.