Skip to content

Commit

Permalink
Merge from release/2.0, add missing tests, change to exception
Browse files Browse the repository at this point in the history
  • Loading branch information
AbrilRBS committed Dec 18, 2023
1 parent df4d43b commit 974b568
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 49 deletions.
2 changes: 1 addition & 1 deletion conan/api/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def _skip_warning():

def error(self, msg, error_type=None):
if self._conan_output_level <= LEVEL_ERROR:
if self._warnings_as_errors and error_type != "context":
if self._warnings_as_errors and error_type != "exception":
raise ConanException(msg)
else:
self._write_message("ERROR: {}".format(msg), Color.RED)
Expand Down
14 changes: 7 additions & 7 deletions conan/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _add_commands(self):
self._add_command(module_name, module_name.replace("cmd_", ""))
except Exception as e:
ConanOutput().error(f"Error loading custom command '{module_name}.py': {e}",
error_type="context")
error_type="exception")
# layers
for folder in os.listdir(custom_commands_path):
layer_folder = os.path.join(custom_commands_path, folder)
Expand All @@ -68,7 +68,7 @@ def _add_commands(self):
package=folder)
except Exception as e:
ConanOutput().error(f"Error loading custom command {module_path}: {e}",
error_type="context")
error_type="exception")

def _add_command(self, import_path, method_name, package=None):
try:
Expand Down Expand Up @@ -209,20 +209,20 @@ def exception_exit_error(exception):
if exception is None:
return SUCCESS
if isinstance(exception, ConanInvalidConfiguration):
output.error(exception, error_type="context")
output.error(exception, error_type="exception")
return ERROR_INVALID_CONFIGURATION
if isinstance(exception, ConanException):
output.error(exception, error_type="context")
output.error(exception, error_type="exception")
return ERROR_GENERAL
if isinstance(exception, SystemExit):
if exception.code != 0:
output.error("Exiting with code: %d" % exception.code, error_type="context")
output.error("Exiting with code: %d" % exception.code, error_type="exception")
return exception.code

assert isinstance(exception, Exception)
output.error(traceback.format_exc(), error_type="context")
output.error(traceback.format_exc(), error_type="exception")
msg = exception_message_safe(exception)
output.error(msg, error_type="context")
output.error(msg, error_type="exception")
return ERROR_UNEXPECTED


Expand Down
2 changes: 1 addition & 1 deletion conan/internal/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def _deploy_single(dep, conanfile, output_folder, folder_name):
except Exception as e:
if "WinError 1314" in str(e):
ConanOutput().error("full_deploy: Symlinks in Windows require admin privileges "
"or 'Developer mode = ON'", error_type="context")
"or 'Developer mode = ON'", error_type="exception")
raise ConanException(f"full_deploy: The copy of '{dep}' files failed: {e}.\nYou can "
f"use 'tools.deployer:symlinks' conf to disable symlinks")
dep.set_deploy_folder(new_folder)
Expand Down
12 changes: 6 additions & 6 deletions conan/internal/integrity_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ def _recipe_corrupted(self, ref: RecipeReference):
if not k.startswith("export_source")}

if read_manifest != expected_manifest:
output.error(f"{ref}: Manifest mismatch", error_type="context")
output.error(f"Folder: {layout.export()}", error_type="context")
output.error(f"{ref}: Manifest mismatch", error_type="exception")
output.error(f"Folder: {layout.export()}", error_type="exception")
diff = read_manifest.difference(expected_manifest)
for fname, (h1, h2) in diff.items():
output.error(f" '{fname}' (manifest: {h1}, file: {h2})", error_type="context")
output.error(f" '{fname}' (manifest: {h1}, file: {h2})", error_type="exception")
return True
output.info(f"{ref}: Integrity checked: ok")

Expand All @@ -55,10 +55,10 @@ def _package_corrupted(self, ref: PkgReference):
read_manifest, expected_manifest = layout.package_manifests()

if read_manifest != expected_manifest:
output.error(f"{ref}: Manifest mismatch", error_type="context")
output.error(f"Folder: {layout.package()}", error_type="context")
output.error(f"{ref}: Manifest mismatch", error_type="exception")
output.error(f"Folder: {layout.package()}", error_type="exception")
diff = read_manifest.difference(expected_manifest)
for fname, (h1, h2) in diff.items():
output.error(f" '{fname}' (manifest: {h1}, file: {h2})", error_type="context")
output.error(f" '{fname}' (manifest: {h1}, file: {h2})", error_type="exception")
return True
output.info(f"{ref}: Integrity checked: ok")
4 changes: 2 additions & 2 deletions conan/tools/files/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def print_progress(_, __):
try:
z.extract(file_, full_path)
except Exception as e:
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="context")
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="exception")
else: # duplicated for, to avoid a platform check for each zipped file
for file_ in zip_info:
extracted_size += file_.file_size
Expand All @@ -352,7 +352,7 @@ def print_progress(_, __):
perm = file_.external_attr >> 16 & 0xFFF
os.chmod(os.path.join(full_path, file_.filename), perm)
except Exception as e:
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="context")
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="exception")
output.writeln("")


Expand Down
2 changes: 1 addition & 1 deletion conans/client/cmd/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def cmd_export(app, global_conf, conanfile_path, name, version, user, channel, g
clean_dirty(source_folder)
except BaseException as e:
scoped_output.error("Unable to delete source folder. Will be marked as corrupted "
"for deletion", error_type="context")
"for deletion", error_type="exception")
scoped_output.warning(str(e))
set_dirty(source_folder)

Expand Down
2 changes: 1 addition & 1 deletion conans/client/generators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def write_generators(conanfile, app):
continue
except Exception as e:
# When a generator fails, it is very useful to have the whole stacktrace
conanfile.output.error(traceback.format_exc(), error_type="context")
conanfile.output.error(traceback.format_exc(), error_type="exception")
raise ConanException(f"Error in generator '{generator_name}': {str(e)}") from e
finally:
# restore the generators attribute, so it can raise
Expand Down
2 changes: 1 addition & 1 deletion conans/client/graph/install_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def _raise_missing(self, missing):
missing_prefs_str = list(sorted([str(pref) for pref in missing_prefs]))
out = ConanOutput()
for pref_str in missing_prefs_str:
out.error(f"Missing binary: {pref_str}", error_type="context")
out.error(f"Missing binary: {pref_str}", error_type="exception")
out.writeln("")

# Report details just the first one
Expand Down
2 changes: 1 addition & 1 deletion conans/client/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _build(self, conanfile, pref):
conanfile.output.success("Package '%s' built" % pref.package_id)
conanfile.output.info("Build folder %s" % conanfile.build_folder)
except Exception as exc:
conanfile.output.error(f"\nPackage '{pref.package_id}' build failed", error_type="context")
conanfile.output.error(f"\nPackage '{pref.package_id}' build failed", error_type="exception")
conanfile.output.warning("Build folder %s" % conanfile.build_folder)
if isinstance(exc, ConanException):
raise exc
Expand Down
2 changes: 1 addition & 1 deletion conans/client/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def _migrate_pkg_db_lru(cache_folder, old_version):
except Exception:
ConanOutput().error(f"Could not complete the 2.0.14 DB migration."
" Please manually remove your .conan2 cache and reinstall packages",
error_type="context")
error_type="exception")
raise
else: # generate the back-migration script
undo_lru = textwrap.dedent("""\
Expand Down
12 changes: 6 additions & 6 deletions conans/client/remote_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def get_recipe(self, ref, remote, metadata=None):
f"no conanmanifest.txt")
self._signer.verify(ref, download_export, files=zipped_files)
except BaseException: # So KeyboardInterrupt also cleans things
ConanOutput(scope=str(ref)).error(f"Error downloading from remote '{remote.name}'", error_type="context")
ConanOutput(scope=str(ref)).error(f"Error downloading from remote '{remote.name}'", error_type="exception")
self._cache.remove_recipe_layout(layout)
raise
export_folder = layout.export()
Expand Down Expand Up @@ -91,7 +91,7 @@ def get_recipe_metadata(self, ref, remote, metadata):
self._call_remote(remote, "get_recipe", ref, download_export, metadata,
only_metadata=True)
except BaseException: # So KeyboardInterrupt also cleans things
output.error(f"Error downloading metadata from remote '{remote.name}'", error_type="context")
output.error(f"Error downloading metadata from remote '{remote.name}'", error_type="exception")
raise

def get_recipe_sources(self, ref, layout, remote):
Expand Down Expand Up @@ -134,8 +134,8 @@ def get_package_metadata(self, pref, remote, metadata):
self._call_remote(remote, "get_package", pref, download_pkg_folder,
metadata, only_metadata=True)
except BaseException as e: # So KeyboardInterrupt also cleans things
output.error(f"Exception while getting package metadata: {str(pref.package_id)}", error_type="context")
output.error(f"Exception: {type(e)} {str(e)}", error_type="context")
output.error(f"Exception while getting package metadata: {str(pref.package_id)}", error_type="exception")
output.error(f"Exception: {type(e)} {str(e)}", error_type="exception")
raise

def _get_package(self, layout, pref, remote, scoped_output, metadata):
Expand Down Expand Up @@ -166,8 +166,8 @@ def _get_package(self, layout, pref, remote, scoped_output, metadata):
raise PackageNotFoundException(pref)
except BaseException as e: # So KeyboardInterrupt also cleans things
self._cache.remove_package_layout(layout)
scoped_output.error(f"Exception while getting package: {str(pref.package_id)}", error_type="context")
scoped_output.error(f"Exception: {type(e)} {str(e)}", error_type="context")
scoped_output.error(f"Exception while getting package: {str(pref.package_id)}", error_type="exception")
scoped_output.error(f"Exception: {type(e)} {str(e)}", error_type="exception")
raise

def search_recipes(self, remote, pattern):
Expand Down
6 changes: 3 additions & 3 deletions conans/client/rest/auth_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ def _retry_with_new_token(self, user, remote, method_name, *args, **kwargs):
except AuthenticationException:
out = ConanOutput()
if user is None:
out.error('Wrong user or password', error_type="context")
out.error('Wrong user or password', error_type="exception")
else:
out.error(f'Wrong password for user "{user}"', error_type="context")
out.error(f'Wrong password for user "{user}"', error_type="exception")
out.info('You can change username with "conan remote login <remote> <username>"')
else:
return self.call_rest_api_method(remote, method_name, *args, **kwargs)
Expand All @@ -98,7 +98,7 @@ def _clear_user_tokens_in_db(self, user, remote):
self._localdb.store(user, token=None, refresh_token=None, remote_url=remote.url)
except Exception as e:
out = ConanOutput()
out.error('Your credentials could not be stored in local cache\n', error_type="context")
out.error('Your credentials could not be stored in local cache\n', error_type="exception")
out.debug(str(e) + '\n')

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion conans/client/rest/rest_client_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def _upload_files(self, files, urls):
except (AuthenticationException, ForbiddenException):
raise
except Exception as exc:
output.error(f"\nError uploading file: {filename}, '{exc}'", error_type="context")
output.error(f"\nError uploading file: {filename}, '{exc}'", error_type="exception")
failed.append(filename)

if failed:
Expand Down
4 changes: 2 additions & 2 deletions conans/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def migrate(self):
self._apply_back_migrations()
self._update_version_file()
except Exception as e:
ConanOutput().error(str(e), error_type="context")
ConanOutput().error(str(e), error_type="exception")
raise ConanMigrationError(e)

def _update_version_file(self):
Expand Down Expand Up @@ -82,5 +82,5 @@ def _apply_back_migrations(self):
except Exception as e:
ConanOutput().error(f"There was an error running downgrade migration: {e}. "
f"Recommended to remove the cache and start from scratch",
error_type="context")
error_type="exception")
os.remove(migration)
2 changes: 1 addition & 1 deletion conans/model/graph_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def resolve_locked(self, node, require, resolve_prereleases):
msg = f"Override defined for {require.ref}, but multiple possible overrides" \
f" {overrides}. You might need to apply the 'conan graph build-order'" \
f" overrides for correctly building this package with this lockfile"
ConanOutput().error(msg, error_type="context")
ConanOutput().error(msg, error_type="exception")
raise

def _resolve_overrides(self, require):
Expand Down
85 changes: 71 additions & 14 deletions conans/test/integration/command_v2/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient
from conans.util.env import environment_update


class TestOutputLevel:
def test_invalid_output_level(self):
t = TestClient()
t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile("foo", "1.0")})
t.run("create . -vfooling", assert_error=True)
assert "Invalid argument '-vfooling'"
Expand All @@ -23,7 +24,7 @@ def test_output_level(self):
"self.output.error('This is a error')",
)

t = TestClient()
t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*lines)})

# By default, it prints > info
Expand Down Expand Up @@ -144,37 +145,79 @@ def test_output_level(self):
assert "This is a error" in t.out


def test_output_level_envvar():
lines = ("self.output.trace('This is a trace')",
"self.output.debug('This is a debug')",
"self.output.verbose('This is a verbose')",
"self.output.info('This is a info')",
"self.output.highlight('This is a highlight')",
"self.output.success('This is a success')",
"self.output.warning('This is a warning')",
"self.output.error('This is a error')",
)

t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile().with_package(*lines)})

# Check if -v argument is equal to VERBOSE level
with environment_update({"CONAN_LOG_LEVEL": "verbose"}):
t.run("create . --name foo --version 1.0")
assert "This is a trace" not in t.out
assert "This is a debug" not in t.out
assert "This is a verbose" in t.out
assert "This is a info" in t.out
assert "This is a highlight" in t.out
assert "This is a success" in t.out
assert "This is a warning" in t.out
assert "This is a error" in t.out

# Check if -v argument is equal to VERBOSE level
with environment_update({"CONAN_LOG_LEVEL": "error"}):
t.run("create . --name foo --version 1.0")
assert "This is a trace" not in t.out
assert "This is a debug" not in t.out
assert "This is a verbose" not in t.out
assert "This is a info" not in t.out
assert "This is a highlight" not in t.out
assert "This is a success" not in t.out
assert "This is a warning" not in t.out
assert "This is a error" in t.out


class TestWarningHandling:
lines = ("self.output.warning('Untagged warning')",
"self.output.warning('Tagged warning', warn_tag='tag')")
warning_lines = ("self.output.warning('Tagged warning', warn_tag='tag')",
"self.output.warning('Untagged warning')")
error_lines = ("self.output.error('Tagged error', error_type='exception')",
"self.output.error('Untagged error')")

def test_warning_as_error(self):
t = TestClient()
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.lines)})
t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.warning_lines)})

t.save_home({"global.conf": "core:warnings_as_errors=False"})
t.run("create . -vwarning")
assert "WARN: Untagged warning" in t.out
assert "WARN: tag: Tagged warning" in t.out

t.save_home({"global.conf": "core:warnings_as_errors=True"})
t.run("create . -vwarning")
assert "ERROR: Untagged warning" in t.out
assert "ERROR: tag: Tagged warning" in t.out
t.run("create . -vwarning", assert_error=True)
assert "ConanException: tag: Tagged warning" in t.out
# We bailed early, didn't get a chance to print this one
assert "Untagged warning" not in t.out

t.save_home({"global.conf": """core:warnings_as_errors=True\ncore:skip_warnings=["tag"]"""})
t.run("create . -verror")
assert "ERROR: Untagged warning" in t.out
assert "ERROR: tag: Tagged warning" not in t.out
t.run("create . -verror", assert_error=True)
assert "ConanException: Untagged warning" in t.out
assert "Tagged warning" not in t.out

t.save_home({"global.conf": "core:warnings_as_errors=False"})
t.run("create . -verror")
assert "ERROR: Untagged warning" not in t.out
assert "ERROR: tag: Tagged warning" not in t.out

def test_skip_warnings(self):
t = TestClient()
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.lines)})
t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.warning_lines)})

t.save_home({"global.conf": "core:skip_warnings=[]"})
t.run("create . -vwarning")
Expand All @@ -195,3 +238,17 @@ def test_skip_warnings(self):
t.run("create . -vwarning")
assert "WARN: Untagged warning" not in t.out
assert "WARN: tag: Tagged warning" not in t.out

def test_exception_errors(self):
t = TestClient(light=True)
t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.error_lines)})

t.save_home({"global.conf": "core:warnings_as_errors=False"})
t.run("create .")
assert "ERROR: Tagged error" in t.out
assert "ERROR: Untagged error" in t.out

t.save_home({"global.conf": "core:warnings_as_errors=True"})
t.run("create .", assert_error=True)
assert "ERROR: Tagged error" in t.out
assert "ConanException: Untagged error" in t.out

0 comments on commit 974b568

Please sign in to comment.