From 8df3fb3e7c63aec4ae1f0c672ffe54eb64db248a Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Wed, 23 Oct 2024 17:14:07 -0400 Subject: [PATCH 1/7] lint: update avocado-static-checks For the sake of incorporating a fix on check-lint, where the return code signals any failures in the executed checks, as opposed to just the last check. Signed-off-by: Cleber Rosa --- static-checks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static-checks b/static-checks index aac9062d44..8a2c5dfd1c 160000 --- a/static-checks +++ b/static-checks @@ -1 +1 @@ -Subproject commit aac9062d443c622258ed1199de1014634d15a60d +Subproject commit 8a2c5dfd1c0c576534b31c55439cf631599edb6c From b8f238d16b839493294f98a3c67789cdd72c1bd6 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Wed, 23 Oct 2024 17:19:35 -0400 Subject: [PATCH 2/7] lint: introduce pylint configuration for utils In order to have "avocado/utils" in a way that can be easily transported to the autils project, it's necessary to have the closest lint configuration possible (ideally, the same). This introduces a configuration file that is a copy of the existing ".pylintrc" file. The goal is that further commits will address other warnings and bring the exceptions as close as possible to the "avocado-static-checks" default pylint configuration file, which has no exceptions. Signed-off-by: Cleber Rosa --- .pylintrc_utils | 547 +++++++++++++++++++++++++++++++++++++ avocado-static-checks.conf | 1 + 2 files changed, 548 insertions(+) create mode 100644 .pylintrc_utils diff --git a/.pylintrc_utils b/.pylintrc_utils new file mode 100644 index 0000000000..59f94b7329 --- /dev/null +++ b/.pylintrc_utils @@ -0,0 +1,547 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-whitelist=netifaces + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns=.git + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=0 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins=pylint.extensions.no_self_use + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=all + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then re-enable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=C0103, + C0114, + C0115, + C0116, + C0200, + C0201, + C0301, + C0302, + C0321, + C0325, + C0413, + C0415, + C1804, + C1805, + E0401, + E0611, + E1101, + E1120, + I0011, + I0020, + I0021, + I0022, + I0023, + R0201, + R0801, + R0901, + R0902, + R0903, + R0904, + R0911, + R0912, + R0913, + R0914, + R0915, + R1702, + R1703, + R1704, + R1705, + R1706, + R1710, + R1711, + R1714, + R1717, + R1718, + R1719, + R1720, + R1721, + R1722, + R1723, + R1724, + R1729, + R1730, + R1732, + W0212, + W0511, + W0703, + W0707, + W1203 + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages. +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit + + +[STRING] + +# This flag controls whether the implicit-str-concat-in-sequence should +# generate a warning on implicit string concatenation in sequences defined over +# several lines. +check-str-concat-over-line-jumps=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +#class-attribute-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +#variable-rgx= + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: en_ZM (myspell), en_ZW +# (myspell), en_US (myspell), en_PH (myspell), en_IN (myspell), en_BW +# (myspell), en_TT (myspell), en_GB (myspell), en_SG (myspell), en_AG +# (myspell), en_NG (myspell), en_CA (myspell), en_BS (myspell), en_AU +# (myspell), en_JM (myspell), en_ZA (myspell), en_HK (myspell), en_BZ +# (myspell), en_IE (myspell), en_NZ (myspell), en_DK (myspell), en_MW +# (myspell), en_NA (myspell), en_GH (myspell).. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[LOGGING] + +# Format style used to check logging format string. `old` means using % +# formatting, while `new` is for `{}` formatting. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled). +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled). +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement. +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=cls + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "BaseException, Exception". +overgeneral-exceptions=builtin.BaseException, + builtin.Exception diff --git a/avocado-static-checks.conf b/avocado-static-checks.conf index 1248049bef..c9d0903a3d 100644 --- a/avocado-static-checks.conf +++ b/avocado-static-checks.conf @@ -1,2 +1,3 @@ [lint] +avocado/utils:.pylintrc_utils .:.pylintrc From cf7574508b7de1bd7fbff7ec29e89fa054edec55 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 14 Oct 2024 04:58:14 -0400 Subject: [PATCH 3/7] lint: address W1203 / logging-fstring-interpolation For this change, there was the possibility of making changes compatible with "logging-format-style=old" (the default), or jumping the gun and making changes compatible with "logging-format-style=new". The earlier approach was chosen because the goal is to get closer to: * A default pylint configuration (as shipped/generated by pylint itself) * The configuration provided by avocado-static-checks and used by autils Reference: https://pylint.pycqa.org/en/latest/user_guide/messages/warning/logging-fstring-interpolation.html Signed-off-by: Cleber Rosa --- .pylintrc_utils | 4 +--- avocado/utils/archive.py | 4 ++-- avocado/utils/asset.py | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.pylintrc_utils b/.pylintrc_utils index 59f94b7329..aebe9b4ea7 100644 --- a/.pylintrc_utils +++ b/.pylintrc_utils @@ -122,9 +122,7 @@ disable=C0103, W0212, W0511, W0703, - W0707, - W1203 - + W0707 [REPORTS] diff --git a/avocado/utils/archive.py b/avocado/utils/archive.py index 1d6b4a3052..fb3a819087 100644 --- a/avocado/utils/archive.py +++ b/avocado/utils/archive.py @@ -297,7 +297,7 @@ def _update_zip_extra_attrs(self, dst_dir): os.remove(dst) os.symlink(src, dst) except Exception as e: - LOG.warning(f"Failed to update symlink '{dst}': {str(e)}") + LOG.warning("Failed to update symlink '%s': %s", dst, e) continue continue # Don't override any other attributes on links mode = attr & 511 # Mask only permissions @@ -305,7 +305,7 @@ def _update_zip_extra_attrs(self, dst_dir): try: os.chmod(dst, mode) except Exception as e: - LOG.warning(f"Failed to update permissions for '{dst}': {str(e)}") + LOG.warning("Failed to update permissions for '%s'", e) def close(self): """ diff --git a/avocado/utils/asset.py b/avocado/utils/asset.py index 27326d9510..2ac93583f1 100644 --- a/avocado/utils/asset.py +++ b/avocado/utils/asset.py @@ -689,9 +689,9 @@ def remove_asset_by_path(cls, asset_path): filename = f"{asset_path}-CHECKSUM" os.remove(filename) except FileNotFoundError: - LOG.error(f"File not found: {asset_path} or its checksum file.") + LOG.error("File not found: %s or its checksum file.", asset_path) except Exception as e: - LOG.error(f"An error occurred while removing files: {e}") + LOG.error("An error occurred while removing files: %s", e) @property def urls(self): From 66c549d9fdbcf7b5614f4040e9dc259a53e1823e Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 14 Oct 2024 04:58:14 -0400 Subject: [PATCH 4/7] lint: address raise-missing-from / W0707 Reference: https://pylint.pycqa.org/en/latest/user_guide/messages/warning/raise-missing-from.html Signed-off-by: Cleber Rosa --- .pylintrc_utils | 3 +- avocado/utils/ar.py | 4 +-- avocado/utils/asset.py | 12 +++---- avocado/utils/astring.py | 4 +-- avocado/utils/cpu.py | 6 ++-- avocado/utils/data_structures.py | 12 +++---- avocado/utils/disk.py | 12 +++---- avocado/utils/download.py | 4 +-- avocado/utils/filelock.py | 6 ++-- avocado/utils/gdb.py | 4 +-- avocado/utils/genio.py | 2 +- avocado/utils/linux.py | 4 +-- avocado/utils/lv_utils.py | 20 ++++++------ avocado/utils/multipath.py | 6 ++-- avocado/utils/network/hosts.py | 8 +++-- avocado/utils/network/interfaces.py | 50 +++++++++++++++-------------- avocado/utils/partition.py | 26 +++++++++------ avocado/utils/pci.py | 2 +- avocado/utils/ssh.py | 2 +- avocado/utils/sysinfo.py | 28 +++++++++------- avocado/utils/vmimage.py | 4 +-- 21 files changed, 118 insertions(+), 101 deletions(-) diff --git a/.pylintrc_utils b/.pylintrc_utils index aebe9b4ea7..831e3d7760 100644 --- a/.pylintrc_utils +++ b/.pylintrc_utils @@ -121,8 +121,7 @@ disable=C0103, R1732, W0212, W0511, - W0703, - W0707 + W0703 [REPORTS] diff --git a/avocado/utils/ar.py b/avocado/utils/ar.py index 67b84cb6f5..369d68cffd 100644 --- a/avocado/utils/ar.py +++ b/avocado/utils/ar.py @@ -80,8 +80,8 @@ def __next__(self): member = struct.unpack( FILE_HEADER_FMT, open_file.read(FILE_HEADER_SIZE) ) - except struct.error: - raise StopIteration + except struct.error as exc: + raise StopIteration from exc # No support for extended file names identifier = member[0].decode("ascii").strip() diff --git a/avocado/utils/asset.py b/avocado/utils/asset.py index 2ac93583f1..cd1088b5d1 100644 --- a/avocado/utils/asset.py +++ b/avocado/utils/asset.py @@ -485,8 +485,8 @@ def get_metadata(self): """ try: asset_file = self.find_asset_file() - except OSError: - raise OSError("Metadata not available.") + except OSError as exc: + raise OSError("Metadata not available.") from exc basename = os.path.splitext(asset_file)[0] metadata_file = f"{basename}_metadata.json" @@ -588,21 +588,21 @@ def get_assets_by_size(cls, size_filter, cache_dirs): try: op = re.match("^(\\D+)(\\d+)$", size_filter).group(1) value = int(re.match("^(\\D+)(\\d+)$", size_filter).group(2)) - except (AttributeError, ValueError): + except (AttributeError, ValueError) as exc: msg = ( "Invalid syntax. You need to pass an comparison operatator", " and a value. Ex: '>=200'", ) - raise OSError(msg) + raise OSError(msg) from exc try: method = SUPPORTED_OPERATORS[op] - except KeyError: + except KeyError as exc: msg = ( "Operator not supported. Currented valid values are: ", ", ".join(SUPPORTED_OPERATORS), ) - raise OSError(msg) + raise OSError(msg) from exc result = [] for file_path in cls.get_all_assets(cache_dirs): diff --git a/avocado/utils/astring.py b/avocado/utils/astring.py index eb848b8905..05ca2e6525 100644 --- a/avocado/utils/astring.py +++ b/avocado/utils/astring.py @@ -133,12 +133,12 @@ def strip_console_codes(output, custom_codes=None): continue try: special_code = re.findall(console_codes, tmp_word)[0] - except IndexError: + except IndexError as exc: if index + tmp_index < len(output): raise ValueError( f"{tmp_word} is not included in the known " f"console codes list {console_codes}" - ) + ) from exc continue if special_code == tmp_word: continue diff --git a/avocado/utils/cpu.py b/avocado/utils/cpu.py index 7fe545b2cc..0e86cfa371 100644 --- a/avocado/utils/cpu.py +++ b/avocado/utils/cpu.py @@ -256,7 +256,7 @@ def get_family(): except FileNotFoundError as err: msg = f"Could not find micro-architecture/family, Error: {err}" LOG.warning(msg) - raise FamilyException(msg) + raise FamilyException(msg) from err elif arch == "powerpc": res = [] try: @@ -268,7 +268,7 @@ def get_family(): except IndexError as err: msg = f"Unable to parse cpu family {err}" LOG.warning(msg) - raise FamilyException(msg) + raise FamilyException(msg) from err elif arch == "s390": zfamily_map = {"2964": "z13", "3906": "z14", "8561": "z15", "3931": "z16"} try: @@ -276,7 +276,7 @@ def get_family(): except KeyError as err: msg = f"Could not find family for {get_version()}\nError: {err}" LOG.warning(msg) - raise FamilyException(msg) + raise FamilyException(msg) from err else: raise NotImplementedError return family diff --git a/avocado/utils/data_structures.py b/avocado/utils/data_structures.py index 5b1e803119..618d359440 100644 --- a/avocado/utils/data_structures.py +++ b/avocado/utils/data_structures.py @@ -53,8 +53,8 @@ def geometric_mean(values): """ try: values = [int(value) for value in values] - except ValueError: - raise ValueError(f"Invalid inputs {values}. Provide valid inputs") + except ValueError as exc: + raise ValueError(f"Invalid inputs {values}. Provide valid inputs") from exc no_values = len(values) if no_values == 0: return None @@ -293,12 +293,12 @@ def time_to_seconds(time): seconds = int(time[:-1]) * mult else: seconds = int(time) - except (ValueError, TypeError): + except (ValueError, TypeError) as exc: raise ValueError( f"Invalid value '{time}' for time. Use a string " f"with the number and optionally the time unit " f"(s, m, h or d)." - ) + ) from exc else: seconds = 0 return seconds @@ -339,10 +339,10 @@ def __init__(self, data): if self._value < 0: raise ValueError - except ValueError: + except ValueError as exc: raise InvalidDataSize( 'String not in size + unit format (i.e. "10M", "100k", ...)' - ) + ) from exc @property def value(self): diff --git a/avocado/utils/disk.py b/avocado/utils/disk.py index a2549fca45..33cc64d586 100644 --- a/avocado/utils/disk.py +++ b/avocado/utils/disk.py @@ -124,11 +124,11 @@ def get_disks(): try: json_result = process.run("lsblk --json --paths --inverse") except process.CmdError as ce: - raise DiskError(f"Error occurred while executing lsblk command: {ce}") + raise DiskError(f"Error occurred while executing lsblk command: {ce}") from ce try: json_data = json.loads(json_result.stdout_text) except json.JSONDecodeError as je: - raise DiskError(f"Error occurred while parsing JSON data: {je}") + raise DiskError(f"Error occurred while parsing JSON data: {je}") from je disks = [] for device in json_data["blockdevices"]: disks.append(device["name"]) @@ -359,10 +359,10 @@ def create_linux_raw_partition(disk_name, size=None, num_of_par=1): part_output = process.getoutput( "sfdisk " + disk_name + " < " + disk_partition_file ) - except: + except Exception as exc: msg = f"sfdisk partition creation command failed on disk {disk_name}" LOGGER.warning(msg) - raise DiskError(msg) + raise DiskError(msg) from exc rescan_disk(disk_name) if "The partition table has been altered" in part_output: return get_disk_partitions(disk_name) @@ -395,10 +395,10 @@ def delete_partition(partition_name): + " " + partition_name[disk_index:] ) - except: + except Exception as exc: msg = f"sfdisk --delete command failed on disk {partition_name}" LOGGER.warning(msg) - raise DiskError(msg) + raise DiskError(msg) from exc def clean_disk(disk_name): diff --git a/avocado/utils/download.py b/avocado/utils/download.py index 6798826b87..740e7259ec 100644 --- a/avocado/utils/download.py +++ b/avocado/utils/download.py @@ -121,8 +121,8 @@ def url_download_interactive(url, output_file, title="", chunk_size=102400): try: file_size = int(input_file.headers["Content-Length"]) - except KeyError: - raise ValueError("Could not find file size in HTTP headers") + except KeyError as exc: + raise ValueError("Could not find file size in HTTP headers") from exc log.info( "Downloading %s, %s to %s", diff --git a/avocado/utils/filelock.py b/avocado/utils/filelock.py index cc75a5f0ad..5421475d04 100644 --- a/avocado/utils/filelock.py +++ b/avocado/utils/filelock.py @@ -55,7 +55,7 @@ def __enter__(self): os.close(fd) self.locked = True return self - except Exception: # pylint: disable=W0703 + except Exception as exc: # pylint: disable=W0703 try: # Read the file to realize what's happening. with open(self.filename, "r", encoding="utf-8") as f: @@ -80,9 +80,9 @@ def __enter__(self): # to a running process and we are just waiting for the lock # to be released. if self.timeout <= 0: - raise AlreadyLocked("File is already locked.") + raise AlreadyLocked("File is already locked.") from exc elif time.monotonic() > timelimit: - raise AlreadyLocked("Timeout waiting for the lock.") + raise AlreadyLocked("Timeout waiting for the lock.") from exc else: time.sleep(0.1) diff --git a/avocado/utils/gdb.py b/avocado/utils/gdb.py index ee48ca0f19..11238ab4b7 100644 --- a/avocado/utils/gdb.py +++ b/avocado/utils/gdb.py @@ -284,7 +284,7 @@ def __init__(self, path=None, *extra_args): # pylint: disable=W1113 if details.errno == 2: exc = OSError(f"File '{args[0]}' not found") exc.errno = 2 - raise exc + raise exc from details else: raise @@ -613,7 +613,7 @@ def __init__( if details.errno == 2: exc = OSError(f"File '{args[0]}' not found") exc.errno = 2 - raise exc + raise exc from details else: raise diff --git a/avocado/utils/genio.py b/avocado/utils/genio.py index 837200aff1..a0171ad1ce 100644 --- a/avocado/utils/genio.py +++ b/avocado/utils/genio.py @@ -174,7 +174,7 @@ def write_file_or_fail(filename, data): with open(filename, "w", encoding="utf-8") as file_obj: file_obj.write(data) except OSError as details: - raise GenIOError(f"The write to {filename} failed: {details}") + raise GenIOError(f"The write to {filename} failed: {details}") from details def append_file(filename, data): diff --git a/avocado/utils/linux.py b/avocado/utils/linux.py index 3546c72bd8..43c57d1296 100644 --- a/avocado/utils/linux.py +++ b/avocado/utils/linux.py @@ -93,6 +93,6 @@ def is_os_secureboot_enabled(): for line in process.system_output(cmd).decode("utf-8").splitlines(): if "00000002" in line: return True - except FileNotFoundError: - raise UnsupportedMachineError("lsprop not a supported command") + except FileNotFoundError as exc: + raise UnsupportedMachineError("lsprop not a supported command") from exc return False diff --git a/avocado/utils/lv_utils.py b/avocado/utils/lv_utils.py index cb37c7b136..7158bca907 100644 --- a/avocado/utils/lv_utils.py +++ b/avocado/utils/lv_utils.py @@ -153,7 +153,7 @@ def vg_ramdisk( except process.CmdError as ex: LOGGER.error(ex) vg_ramdisk_cleanup(ramdisk_filename, vg_ramdisk_dir, vg_name, use_tmpfs) - raise LVException(f"Fail to create vg_ramdisk: {ex}") + raise LVException(f"Fail to create vg_ramdisk: {ex}") from ex if not disk: loop_device = result.stdout_text.rstrip() @@ -172,7 +172,7 @@ def vg_ramdisk( vg_ramdisk_cleanup( ramdisk_filename, vg_ramdisk_dir, vg_name, loop_device, use_tmpfs ) - raise LVException(f"Fail to create vg_ramdisk: {ex}") + raise LVException(f"Fail to create vg_ramdisk: {ex}") from ex return ramdisk_filename, vg_ramdisk_dir, vg_name, loop_device @@ -456,7 +456,7 @@ def lv_create( process.run(tp_cmd, sudo=True) except process.CmdError as detail: LOGGER.debug(detail) - raise LVException("Create thin volume pool failed.") + raise LVException("Create thin volume pool failed.") from detail LOGGER.debug("Created thin volume pool: %s", pool_name) lv_cmd += f" --virtualsize {lv_size}" lv_cmd += f" --thin {vg_name}/{pool_name} -y" @@ -467,7 +467,7 @@ def lv_create( process.run(lv_cmd, sudo=True) except process.CmdError as detail: LOGGER.error(detail) - raise LVException("Create thin volume failed.") + raise LVException("Create thin volume failed.") from detail LOGGER.debug("Created thin volume:%s", lv_name) @@ -625,12 +625,12 @@ def lv_reactivate(vg_name, lv_name, timeout=10): time.sleep(timeout) process.run(f"lvchange -ay /dev/{vg_name}/{lv_name}", sudo=True) time.sleep(timeout) - except process.CmdError: + except process.CmdError as exc: log_msg = ( "Failed to reactivate %s - please, nuke the process that uses it first." ) LOGGER.error(log_msg, lv_name) - raise LVException(f"The Logical volume {lv_name} is still active") + raise LVException(f"The Logical volume {lv_name} is still active") from exc def lv_mount(vg_name, lv_name, mount_loc, create_filesystem=""): @@ -650,7 +650,7 @@ def lv_mount(vg_name, lv_name, mount_loc, create_filesystem=""): process.run(f"mkfs.{create_filesystem} /dev/{vg_name}/{lv_name}", sudo=True) process.run(f"mount /dev/{vg_name}/{lv_name} {mount_loc}", sudo=True) except process.CmdError as ex: - raise LVException(f"Fail to mount logical volume: {ex}") + raise LVException(f"Fail to mount logical volume: {ex}") from ex def vg_reactivate(vg_name, timeout=10, export=False): @@ -675,12 +675,12 @@ def vg_reactivate(vg_name, timeout=10, export=False): process.run(f"vgchange -ay {vg_name}", sudo=True) time.sleep(timeout) - except process.CmdError: + except process.CmdError as exc: log_msg = ( "Failed to reactivate %s - please, nuke the process that uses it first." ) LOGGER.error(log_msg, vg_name) - raise LVException(f"The Volume group {vg_name} is still active") + raise LVException(f"The Volume group {vg_name} is still active") from exc def lv_umount(vg_name, lv_name): @@ -694,4 +694,4 @@ def lv_umount(vg_name, lv_name): try: process.run(f"umount /dev/{vg_name}/{lv_name}", sudo=True) except process.CmdError as ex: - raise LVException(f"Fail to unmount logical volume: {ex}") + raise LVException(f"Fail to unmount logical volume: {ex}") from ex diff --git a/avocado/utils/multipath.py b/avocado/utils/multipath.py index cc1efcefaa..bb070bb624 100644 --- a/avocado/utils/multipath.py +++ b/avocado/utils/multipath.py @@ -109,7 +109,7 @@ def get_mpath_from_dm(dm_id): try: mpaths = process.run(cmd, ignore_status=True, sudo=True, shell=True).stdout_text except process.CmdError as ex: - raise MPException(f"Multipathd Command Failed : {ex} ") + raise MPException(f"Multipathd Command Failed : {ex} ") from ex for mpath in mpaths.splitlines(): if dm_id in mpath: return mpath.split()[1] @@ -139,7 +139,7 @@ def get_multipath_wwid(mpath): try: wwids = process.run(cmd, ignore_status=True, sudo=True, shell=True).stdout_text except process.CmdError as ex: - raise MPException(f"Multipathd Command Failed : {ex} ") + raise MPException(f"Multipathd Command Failed : {ex} ") from ex for wwid in wwids.splitlines(): if mpath in wwid: return wwid.split()[1] @@ -156,7 +156,7 @@ def is_mpath_dev(mpath): try: mpaths = process.run(cmd, ignore_status=True, sudo=True, shell=True).stdout_text except process.CmdError as ex: - raise MPException(f"Multipath Command Failed : {ex} ") + raise MPException(f"Multipath Command Failed : {ex} ") from ex if mpath in mpaths.strip("\n").split("\n"): return True return False diff --git a/avocado/utils/network/hosts.py b/avocado/utils/network/hosts.py index ff4d36eee7..0c66ea8f64 100644 --- a/avocado/utils/network/hosts.py +++ b/avocado/utils/network/hosts.py @@ -58,7 +58,7 @@ def interfaces(self): try: names = run_command(cmd, self).split() except Exception as ex: - raise NWException(f"Failed to get interfaces: {ex}") + raise NWException(f"Failed to get interfaces: {ex}") from ex if "bonding_masters" in names: names.remove("bonding_masters") @@ -88,7 +88,7 @@ def get_all_hwaddr(self): result = json.loads(output) return [str(item["address"]) for item in result] except Exception as ex: - raise NWException(f"could not get mac addresses:" f" {ex}") + raise NWException(f"could not get mac addresses:" f" {ex}") from ex def validate_mac_addr(self, mac_id): """Check if mac address is valid. @@ -131,7 +131,9 @@ def get_default_route_interface(self): result = json.loads(output) return [str(item["dev"]) for item in result] except Exception as ex: - raise NWException(f"could not get default route interface name:" f" {ex}") + raise NWException( + f"could not get default route interface name:" f" {ex}" + ) from ex class LocalHost(Host): diff --git a/avocado/utils/network/interfaces.py b/avocado/utils/network/interfaces.py index cb915958e8..6ea1e4e1fe 100644 --- a/avocado/utils/network/interfaces.py +++ b/avocado/utils/network/interfaces.py @@ -113,10 +113,10 @@ def _get_interface_details(self, version=None): if item.get("ifname") == self.name: return item raise NWException("Interface not found") - except (NWException, json.JSONDecodeError): + except (NWException, json.JSONDecodeError) as exc: msg = f"Unable to get the details of interface {self.name}" LOG.error(msg) - raise NWException(msg) + raise NWException(msg) from exc def _get_bondinterface_details(self): cmd = ( @@ -126,8 +126,10 @@ def _get_bondinterface_details(self): try: mode, slaves = run_command(cmd, self.host).splitlines() return {"mode": mode.split(), "slaves": slaves.split()} - except Exception: - raise NWException(f"Slave interface not found for " f"the bond {self.name}") + except Exception as exc: + raise NWException( + f"Slave interface not found for " f"the bond {self.name}" + ) from exc def _move_file_to_backup(self, filename, ignore_missing=True): destination = f"{filename}.backup" @@ -158,7 +160,7 @@ def set_hwaddr(self, hwaddr): try: run_command(cmd, self.self.host, sudo=True) except Exception as ex: - raise NWException(f"Adding hw address fails: {ex}") + raise NWException(f"Adding hw address fails: {ex}") from ex def add_ipaddr(self, ipaddr, netmask): """Add an IP Address (with netmask) to the interface. @@ -177,7 +179,7 @@ def add_ipaddr(self, ipaddr, netmask): try: run_command(cmd, self.host, sudo=True) except Exception as ex: - raise NWException(f"Failed to add address {ex}") + raise NWException(f"Failed to add address {ex}") from ex @property def vlans(self): @@ -218,7 +220,7 @@ def add_vlan_tag(self, vlan_num, vlan_name=None): try: run_command(cmd, self.host, sudo=True) except Exception as ex: - raise NWException(f"Failed to add VLAN tag: {ex}") + raise NWException(f"Failed to add VLAN tag: {ex}") from ex def remove_vlan_by_tag(self, vlan_num): """Remove the VLAN of the interface by tag number. @@ -240,7 +242,7 @@ def remove_vlan_by_tag(self, vlan_num): run_command(cmd, self.host, sudo=True) return True except Exception as ex: - raise NWException(f"Failed to remove VLAN interface: {ex}") + raise NWException(f"Failed to remove VLAN interface: {ex}") from ex def remove_all_vlans(self): """Remove all VLANs of this interface. @@ -253,7 +255,7 @@ def remove_all_vlans(self): cmd = f"ip link delete {v}" run_command(cmd, self.host, sudo=True) except Exception as ex: - raise NWException(f"Failed to remove VLAN interface: {ex}") + raise NWException(f"Failed to remove VLAN interface: {ex}") from ex def bring_down(self): """Shutdown the interface. @@ -268,7 +270,7 @@ def bring_down(self): try: run_command(cmd, self.host, sudo=True) except Exception as ex: - raise NWException(f"Failed to bring down: {ex}") + raise NWException(f"Failed to bring down: {ex}") from ex def bring_up(self): """ "Wake-up the interface. @@ -281,7 +283,7 @@ def bring_up(self): try: run_command(cmd, self.host, sudo=True) except Exception as ex: - raise NWException(f"Failed to bring up: {ex}") + raise NWException(f"Failed to bring up: {ex}") from ex def is_admin_link_up(self): """Check the admin link state is up or not. @@ -292,8 +294,8 @@ def is_admin_link_up(self): try: if "UP" in self._get_interface_details().get("flags"): return True - except (NWException, IndexError): - raise NWException("Could not get Administrative link state.") + except (NWException, IndexError) as exc: + raise NWException("Could not get Administrative link state.") from exc return False def is_operational_link_up(self): @@ -305,8 +307,8 @@ def is_operational_link_up(self): try: if "LOWER_UP" in self._get_interface_details().get("flags"): return True - except (NWException, IndexError): - raise NWException("Could not get operational link state.") + except (NWException, IndexError) as exc: + raise NWException("Could not get operational link state.") from exc return False def is_link_up(self): @@ -350,7 +352,7 @@ def get_hwaddr(self): try: return run_command(cmd, self.host) except Exception as ex: - raise NWException(f"Failed to get hw address: {ex}") + raise NWException(f"Failed to get hw address: {ex}") from ex def get_mtu(self): """Return the current MTU value of this interface. @@ -360,8 +362,8 @@ def get_mtu(self): """ try: return self._get_interface_details().get("mtu") - except (NWException, IndexError): - raise NWException("Could not get MUT value.") + except (NWException, IndexError) as exc: + raise NWException("Could not get MUT value.") from exc def ping_check(self, peer_ip, count=2, options=None): """This method will try to ping a peer address (IPv4 or IPv6). @@ -380,7 +382,7 @@ def ping_check(self, peer_ip, count=2, options=None): try: run_command(cmd, self.host) except Exception as ex: - raise NWException(f"Failed to ping: {ex}") + raise NWException(f"Failed to ping: {ex}") from ex def save(self, ipaddr, netmask): """Save current interface IP Address to the system configuration file. @@ -536,7 +538,7 @@ def remove_ipaddr(self, ipaddr, netmask): run_command(cmd, self.host, sudo=True) except Exception as ex: msg = f"Failed to remove ipaddr. {ex}" - raise NWException(msg) + raise NWException(msg) from ex def flush_ipaddr(self): """Flush all the IP address for this interface. @@ -552,7 +554,7 @@ def flush_ipaddr(self): run_command(cmd, self.host, sudo=True) except Exception as ex: msg = f"Failed to flush ipaddr. {ex}" - raise NWException(msg) + raise NWException(msg) from ex def remove_link(self): """Deletes virtual interface link. @@ -568,7 +570,7 @@ def remove_link(self): run_command(cmd, self.host, sudo=True) except Exception as ex: msg = f"Failed to delete link. {ex}" - raise NWException(msg) + raise NWException(msg) from ex def restore_from_backup(self): """Revert interface file from backup. @@ -682,7 +684,7 @@ def restore_slave_cfg_file(self): else: os.remove(slave_config) except Exception as ex: - raise NWException(f"Could not restore the config file {ex}") + raise NWException(f"Could not restore the config file {ex}") from ex def are_packets_lost(self, peer_ip, options=None, sudo=False): """Check packet loss that occurs during ping. @@ -706,7 +708,7 @@ def are_packets_lost(self, peer_ip, options=None, sudo=False): return True except Exception as ex: msg = f"Failed to ping. {ex}" - raise NWException(msg) + raise NWException(msg) from ex def netmask_to_cidr(self, netmask): """Function is used to check the netmask value and convert diff --git a/avocado/utils/partition.py b/avocado/utils/partition.py index 5910e06765..4c67e5655d 100644 --- a/avocado/utils/partition.py +++ b/avocado/utils/partition.py @@ -63,7 +63,7 @@ def __enter__(self): reason = ( f"Unable to obtain '{self.device}' " f"lock in {int(self.timeout)}s" ) - raise PartitionError(self, reason, e) + raise PartitionError(self, reason, e) from e self.mtab = open(self.device) # pylint: disable=W1514 return self @@ -194,7 +194,7 @@ def mkfs(self, fstype=None, args=""): try: process.system_output(f"yes | {mkfs_cmd}", shell=True) except process.CmdError as error: - raise PartitionError(self, "Failed to mkfs", error) + raise PartitionError(self, "Failed to mkfs", error) from error else: self.fstype = fstype @@ -244,7 +244,7 @@ def mount(self, mountpoint=None, fstype=None, args="", mnt_check=True): ).stdout_text.strip() process.system(f"mount {args} {self.device} {mountpoint}", sudo=True) except process.CmdError as details: - raise PartitionError(self, "Mount failed", details) + raise PartitionError(self, "Mount failed", details) from details # Update the fstype as the mount command passed self.fstype = fstype @@ -259,11 +259,11 @@ def _get_pids_on_mountpoint(self, mnt): except OSError as details: msg = f'Could not run lsof to identify processes using "{mnt}"' LOG.error(msg) - raise PartitionError(self, msg, details) + raise PartitionError(self, msg, details) from details except process.CmdError as details: msg = f'Failure executing "{cmd}"' LOG.error(msg) - raise PartitionError(self, msg, details) + raise PartitionError(self, msg, details) from details def _unmount_force(self, mountpoint): """ @@ -276,7 +276,9 @@ def _unmount_force(self, mountpoint): try: process.system(f"kill -9 {int(pid)}", ignore_status=True, sudo=True) except process.CmdError as kill_details: - raise PartitionError(self, "Failed to kill processes", kill_details) + raise PartitionError( + self, "Failed to kill processes", kill_details + ) from kill_details # Unmount try: process.run(f"umount -f {mountpoint}", sudo=True) @@ -284,7 +286,9 @@ def _unmount_force(self, mountpoint): try: process.run(f"umount -l {mountpoint}", sudo=True) except process.CmdError as umount_details: - raise PartitionError(self, "Force unmount failed", umount_details) + raise PartitionError( + self, "Force unmount failed", umount_details + ) from umount_details def unmount(self, force=True): """ @@ -315,11 +319,15 @@ def unmount(self, force=True): self._unmount_force(mountpoint) result = 2 else: - raise PartitionError(self, "Unable to unmount gracefully", details) + raise PartitionError( + self, "Unable to unmount gracefully", details + ) from details if self.loop: try: process.run(f"losetup -d {self.device}", sudo=True) except process.CmdError as details: - raise PartitionError(self, "Unable to cleanup loop device", details) + raise PartitionError( + self, "Unable to cleanup loop device", details + ) from details return result diff --git a/avocado/utils/pci.py b/avocado/utils/pci.py index 0e32817b80..1d7702d2cb 100644 --- a/avocado/utils/pci.py +++ b/avocado/utils/pci.py @@ -422,7 +422,7 @@ def change_domain_check(dom, full_pci_address, def_dom): return False return True except OSError as details: - raise ValueError(f"Change domain check failed: {details}") + raise ValueError(f"Change domain check failed: {details}") from details def reset(full_pci_address): diff --git a/avocado/utils/ssh.py b/avocado/utils/ssh.py index 81bb5545c2..cc614d655c 100644 --- a/avocado/utils/ssh.py +++ b/avocado/utils/ssh.py @@ -283,4 +283,4 @@ def copy_files(self, source, destination, recursive=False): result = process.run(f"{cmd} {options}", ignore_status=True) return result.exit_status == 0 except process.CmdError as exc: - raise NWException(f"failed to copy file {exc}") + raise NWException(f"failed to copy file {exc}") from exc diff --git a/avocado/utils/sysinfo.py b/avocado/utils/sysinfo.py index 6803517237..546610c3c0 100644 --- a/avocado/utils/sysinfo.py +++ b/avocado/utils/sysinfo.py @@ -115,10 +115,10 @@ def collect(self): if os.path.exists(self.path): try: yield from self._read_file(self.path) - except IOError: + except IOError as exc: raise CollectibleException( f"Not logging {self.path} " f"(lack of permissions)" - ) + ) from exc else: raise CollectibleException(f"Not logging {self.path} " f"(file not found)") @@ -183,9 +183,11 @@ def collect(self): f"Not logging '{self.cmd}' " f"(command '{exc_fnf.filename}' " f"was not found)" - ) + ) from exc_fnf except Exception as exc: # pylint: disable=W0703, W0612 - raise CollectibleException(f'Could not execute "{self.cmd}": ' "{exc}") + raise CollectibleException( + f'Could not execute "{self.cmd}": ' "{exc}" + ) from exc class Daemon(Command): @@ -244,7 +246,9 @@ def run(self): env=env, ) except OSError as os_err: - raise CollectibleException(f'Could not execute "{self.cmd}": ' f"{os_err}") + raise CollectibleException( + f'Could not execute "{self.cmd}": ' f"{os_err}" + ) from os_err def collect(self): """ @@ -303,7 +307,9 @@ def _get_cursor(): last_record = json.loads(astring.to_text(result, "utf-8")) return last_record["__CURSOR"] except Exception as detail: # pylint: disable=W0703 - raise CollectibleException(f"Journalctl collection failed: " f"{detail}") + raise CollectibleException( + f"Journalctl collection failed: " f"{detail}" + ) from detail def collect(self): """ @@ -318,7 +324,7 @@ def collect(self): except Exception as detail: # pylint: disable=W0703 raise CollectibleException( f"Journalctl collection failed: " f"{detail}" - ) + ) from detail class LogWatcher(Collectible): @@ -347,10 +353,10 @@ def __init__(self, path, log_path=None): stat = os.stat(path) self.size = stat.st_size self.inode = stat.st_ino - except (IOError, OSError): + except (IOError, OSError) as exc: raise CollectibleException( f"Not logging {self.path} " f"(lack of permissions)" - ) + ) from exc def __repr__(self): r = "LogWatcher(%r, %r)" @@ -383,7 +389,7 @@ def collect(self): self.size = current_size try: yield from self._read_file(self.path, bytes_to_skip) - except (IOError, OSError): + except (IOError, OSError) as exc: raise CollectibleException( f"Not logging {self.path} " f"(lack of permissions)" - ) + ) from exc diff --git a/avocado/utils/vmimage.py b/avocado/utils/vmimage.py index 9daee58181..82a1af32c1 100644 --- a/avocado/utils/vmimage.py +++ b/avocado/utils/vmimage.py @@ -113,8 +113,8 @@ def _feed_html_parser(self, url, parser): try: data = urlopen(url).read() parser.feed(astring.to_text(data, self.HTML_ENCODING)) - except HTTPError: - raise ImageProviderError(f"Cannot open {self.url_versions}") + except HTTPError as exc: + raise ImageProviderError(f"Cannot open {self.url_versions}") from exc @staticmethod def get_best_version(versions): From 4770c14254b4e1abc9344f631d9847065cbc7234 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 14 Oct 2024 04:58:14 -0400 Subject: [PATCH 5/7] lint: remove configuration requirement for broad-except / W0703 The "broad-except" has been renamed to "broad-exception-caught", warning number W0718. So it can be removed from the configuration file. Reference: https://pylint.pycqa.org/en/latest/user_guide/messages/warning/broad-except.html Signed-off-by: Cleber Rosa --- .pylintrc_utils | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc_utils b/.pylintrc_utils index 831e3d7760..dc993bc994 100644 --- a/.pylintrc_utils +++ b/.pylintrc_utils @@ -120,8 +120,7 @@ disable=C0103, R1730, R1732, W0212, - W0511, - W0703 + W0511 [REPORTS] From 667f53b401a2d5d9aedbf37f1f788ae83c4f95c3 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 14 Oct 2024 04:58:14 -0400 Subject: [PATCH 6/7] lint: address fixme / W0511 There are a few occurrences where code is being used to keep track of possible improvements. Many times these will go unnoticed for ages. Let's either document the limitations that are affected by the "TODO"s, or remove them because after quite some time, they were not something that was attempted to be improved or fixed. https://pylint.pycqa.org/en/latest/user_guide/messages/warning/fixme.html Signed-off-by: Cleber Rosa --- .pylintrc_utils | 3 +-- avocado/utils/lv_utils.py | 1 - avocado/utils/process.py | 7 +++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.pylintrc_utils b/.pylintrc_utils index dc993bc994..da9b8fa7e4 100644 --- a/.pylintrc_utils +++ b/.pylintrc_utils @@ -119,8 +119,7 @@ disable=C0103, R1729, R1730, R1732, - W0212, - W0511 + W0212 [REPORTS] diff --git a/avocado/utils/lv_utils.py b/avocado/utils/lv_utils.py index 7158bca907..98f09b2407 100644 --- a/avocado/utils/lv_utils.py +++ b/avocado/utils/lv_utils.py @@ -311,7 +311,6 @@ def vg_list(vg_name=None): lines = lines[1:] else: return vgroups - # TODO: Optimize this for line in lines: details = line.split() details_dict = {} diff --git a/avocado/utils/process.py b/avocado/utils/process.py index bb1cee04cf..94248db766 100644 --- a/avocado/utils/process.py +++ b/avocado/utils/process.py @@ -295,9 +295,11 @@ def process_in_ptree_is_defunct(ppid): Attempt to verify if parent process and any children from PPID is defunct (zombie) or not. + This relies on the GNU version of "ps" and is not guaranteed to work in + MacOS. + :param ppid: The parent PID of the process to verify. """ - # TODO: This relies on the GNU version of ps (need to fix MacOS support) defunct = False try: pids = get_children_pids(ppid) @@ -455,9 +457,6 @@ def __init__( self.fd = fd self.name = name self.data = BytesIO() - # TODO: check if, when the process finishes, the FD doesn't - # automatically close. This may be used as the detection - # instead. self._result = result self._thread = None self._logger = logger From f8537a521080af9b06055e57626a7fa188f58eea Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 14 Oct 2024 04:58:14 -0400 Subject: [PATCH 7/7] lint: remove protected-access / W0212 from configuration No occurrence of this warning was found in avocado/utils. Reference: https://pylint.pycqa.org/en/latest/user_guide/messages/warning/protected-access.html Signed-off-by: Cleber Rosa --- .pylintrc_utils | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.pylintrc_utils b/.pylintrc_utils index da9b8fa7e4..14914a1a74 100644 --- a/.pylintrc_utils +++ b/.pylintrc_utils @@ -118,8 +118,7 @@ disable=C0103, R1724, R1729, R1730, - R1732, - W0212 + R1732 [REPORTS]