From: Thomas Huth <thuth@redhat.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-devel@nongnu.org
Subject: [PULL 1/7] tests/functional/qemu_test: Silence (most) warnings from pylint in asset.py
Date: Mon, 30 Mar 2026 12:28:09 +0200 [thread overview]
Message-ID: <20260330102815.6759-2-thuth@redhat.com> (raw)
In-Reply-To: <20260330102815.6759-1-thuth@redhat.com>
From: Thomas Huth <thuth@redhat.com>
Pylint currently complains:
asset.py:1:0: C0114: Missing module docstring (missing-module-docstring)
asset.py:21:0: C0115: Missing class docstring (missing-class-docstring)
asset.py:28:15: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:34:0: C0115: Missing class docstring (missing-class-docstring)
asset.py:49:15: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:73:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:80:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:83:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:125:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:181:43: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:190:39: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:201:39: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:213:15: W0718: Catching too general exception Exception (broad-exception-caught)
asset.py:218:35: C0209: Formatting a regular string which could be an f-string (consider-using-f-string)
asset.py:125:4: R0912: Too many branches (16/12) (too-many-branches)
asset.py:125:4: R0915: Too many statements (64/50) (too-many-statements)
asset.py:228:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:249:4: C0116: Missing function or method docstring (missing-function-docstring)
asset.py:257:4: C0116: Missing function or method docstring (missing-function-docstring)
Fix all the warnings except for the R0912 and R0915 which will be tackled
in a later commit.
And while we're at it, also add a proper SPDX license identifier.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20260324163543.55503-3-thuth@redhat.com>
---
tests/functional/qemu_test/asset.py | 53 +++++++++++++++++++++--------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py
index 45a2e01e2e6..1cd03c2a9a9 100644
--- a/tests/functional/qemu_test/asset.py
+++ b/tests/functional/qemu_test/asset.py
@@ -1,9 +1,12 @@
-# Test utilities for fetching & caching assets
+# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright 2024 Red Hat, Inc.
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
+'''
+Test utilities for fetching & caching assets
+'''
import hashlib
import logging
@@ -18,21 +21,27 @@
from shutil import copyfileobj
from urllib.error import HTTPError, URLError
+
class AssetError(Exception):
+ '''This exception will be raised if an asset is not usable'''
def __init__(self, asset, msg, transient=False):
self.url = asset.url
self.msg = msg
self.transient = transient
def __str__(self):
- return "%s: %s" % (self.url, self.msg)
+ return f"{self.url}: {self.msg}"
-# Instances of this class must be declared as class level variables
-# starting with a name "ASSET_". This enables the pre-caching logic
-# to easily find all referenced assets and download them prior to
-# execution of the tests.
-class Asset:
+class Asset:
+ '''
+ This class is used to represent an asset that gets downloaded from
+ the internet and will be stored in the local asset cache.
+ Instances of this class must be declared as class level variables
+ starting with a name "ASSET_". This enables the pre-caching logic
+ to easily find all referenced assets and download them prior to
+ execution of the tests.
+ '''
def __init__(self, url, hashsum):
self.url = url
self.hash = hashsum
@@ -46,8 +55,7 @@ def __init__(self, url, hashsum):
self.log = logging.getLogger('qemu-test')
def __repr__(self):
- return "Asset: url=%s hash=%s cache=%s" % (
- self.url, self.hash, self.cache_file)
+ return f"Asset: url={self.url} hash={self.hash} cache={self.cache_file}"
def __str__(self):
return str(self.cache_file)
@@ -71,6 +79,7 @@ def _check(self, cache_file):
return self.hash == hl.hexdigest()
def valid(self):
+ '''Check whether the file exists in the cache and has the right hash'''
if os.getenv("QEMU_TEST_REFRESH_CACHE", None) is not None:
self.log.info("Force refresh of asset %s", self.url)
return False
@@ -78,9 +87,11 @@ def valid(self):
return self.cache_file.exists() and self._check(self.cache_file)
def fetchable(self):
+ '''Check whether we are allowed to download assets from the internet'''
return not os.environ.get("QEMU_TEST_NO_DOWNLOAD", False)
def available(self):
+ '''Check whether the asset is either in the cache or fetchable'''
return self.valid() or self.fetchable()
def _wait_for_other_download(self, tmp_cache_file):
@@ -123,6 +134,7 @@ def _save_time_stamp(self):
self.cache_file.with_suffix(".stamp").write_text(f"{int(time.time())}")
def fetch(self):
+ '''Download the asset from the internet'''
if not self.cache_dir.exists():
self.cache_dir.mkdir(parents=True, exist_ok=True)
@@ -179,7 +191,7 @@ def fetch(self):
# server or networking problem
if e.code == 404:
raise AssetError(self, "Unable to download: "
- "HTTP error %d" % e.code) from e
+ f"HTTP error {e.code}") from e
continue
except URLError as e:
# This is typically a network/service level error
@@ -187,8 +199,9 @@ def fetch(self):
tmp_cache_file.unlink()
self.log.error("Unable to download %s: URL error %s",
self.url, e.reason)
- raise AssetError(self, "Unable to download: URL error %s" %
- e.reason, transient=True) from e
+ raise AssetError(self,
+ f"Unable to download: URL error{e.reason}",
+ transient=True) from e
except ConnectionError as e:
# A socket connection failure, such as dropped conn
# or refused conn
@@ -198,7 +211,7 @@ def fetch(self):
continue
except Exception as e:
tmp_cache_file.unlink()
- raise AssetError(self, "Unable to download: %s" % e,
+ raise AssetError(self, f"Unable to download: {e}",
transient=True) from e
if not os.path.exists(tmp_cache_file):
@@ -210,12 +223,12 @@ def fetch(self):
self.url.encode('utf8'))
os.setxattr(str(tmp_cache_file), "user.qemu-asset-hash",
self.hash.encode('utf8'))
- except Exception as e:
+ except OSError as e:
self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file, e)
if not self._check(tmp_cache_file):
tmp_cache_file.unlink()
- raise AssetError(self, "Hash does not match %s" % self.hash)
+ raise AssetError(self, f"Hash does not match {self.hash}")
tmp_cache_file.replace(self.cache_file)
self._save_time_stamp()
# Remove write perms to stop tests accidentally modifying them
@@ -226,6 +239,10 @@ def fetch(self):
@staticmethod
def precache_test(test):
+ '''
+ Look for variables starting with "ASSET_" and try to fetch the asset
+ that is specified there.
+ '''
log = logging.getLogger('qemu-test')
log.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
@@ -247,6 +264,9 @@ def precache_test(test):
@staticmethod
def precache_suite(suite):
+ '''
+ Iterate through all tests/suites in a suite and precache their assets
+ '''
for test in suite:
if isinstance(test, unittest.TestSuite):
Asset.precache_suite(test)
@@ -255,6 +275,9 @@ def precache_suite(suite):
@staticmethod
def precache_suites(path, cache_tstamp):
+ '''
+ Get the available test suite and precache their assets
+ '''
loader = unittest.loader.defaultTestLoader
tests = loader.loadTestsFromNames([path], None)
--
2.53.0
next prev parent reply other threads:[~2026-03-30 10:28 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-30 10:28 [PULL 0/7] Fixes for QEMU v11.0-rc2 Thomas Huth
2026-03-30 10:28 ` Thomas Huth [this message]
2026-03-30 10:28 ` [PULL 2/7] tests/functional/qemu_test: Split huge fetch() function in asset.py Thomas Huth
2026-03-30 10:28 ` [PULL 3/7] tests/functional/qemu_test: Silence warnings from pylint in config.py Thomas Huth
2026-03-30 10:28 ` [PULL 4/7] hw/display/vga-isa: Fix migration of the isa-vga device Thomas Huth
2026-03-30 10:28 ` [PULL 5/7] hw/display/cirrus_vga_isa: Disable global_vmstate by default for new machines Thomas Huth
2026-03-30 10:28 ` [PULL 6/7] pc-bios: remove obsolete linuxboot.bin prebuilt blob Thomas Huth
2026-03-30 10:28 ` [PULL 7/7] tests/functional/migration.py: Skip migration_with_exec() if socat is not available Thomas Huth
2026-03-30 12:54 ` [PULL 0/7] Fixes for QEMU v11.0-rc2 Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260330102815.6759-2-thuth@redhat.com \
--to=thuth@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.