Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@ jobs = 0

Comment thread
rnetser marked this conversation as resolved.
# Ignore rules that conflict with ruff or are intentionally suppressed.
#
# Handled by ruff formatter (ruff removes noqa comments for these, causing flake8 failures):
# Handled by ruff (suppressed in flake8 to avoid duplicate enforcement):
# E501 — line too long; ruff formatter manages line length
# E201 — whitespace after '('; ruff formatter manages whitespace
# W503 — line break before binary operator; PEP 8 reversed this, ruff uses W504 (after)
# F821 — undefined name; used in global_config files with dynamic exec() loading
# N815 — mixedCaseClassAttribute; enforced by ruff via extend-select, suppressed per-line with # noqa: N815
#
# Suppressed in flake8 only (enforced by ruff via extend-select + per-line # noqa):
# N802 — function name should be lowercase; ast.NodeVisitor/logging.Formatter method overrides
#
# Intentionally suppressed (not enforced by either linter):
# N802 — function name should be lowercase; method overrides like formatTime from logging.Formatter
# TODO: rename exceptions to use Error suffix and remove N818 from ignore
# N818 — exception name should end with Error; existing names like MissingTemplateVariables
ignore = N802, E501, F821, E201, W503, N818
ignore = N802, N815, E501, F821, E201, W503, N818
exclude =
doc,
.tox,
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repos:
stages: [pre-commit]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.1
rev: v0.15.12
hooks:
- id: ruff
stages: [pre-commit]
Expand Down
2 changes: 1 addition & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ def pytest_runtest_setup(item):
if "incremental" in item.keywords:
previousfailed = getattr(item.parent, "_previousfailed", None)
if previousfailed is not None:
pytest.xfail("previous test failed (%s)" % previousfailed.name)
pytest.xfail(f"previous test failed ({previousfailed.name})")


def pytest_runtest_call(item):
Expand Down
2 changes: 1 addition & 1 deletion libs/net/netattachdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class IpamStatic(Ipam):
"""

type: str = field(default="static", init=False)
addresses: list["IpamStatic.Address"]
addresses: list[IpamStatic.Address]
routes: list[IpamRoute] | None = None

@dataclass
Expand Down
15 changes: 8 additions & 7 deletions libs/net/traffic_generator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import contextlib
import logging
from abc import ABC, abstractmethod
from typing import Final, Generator
from collections.abc import Generator
from typing import Final, Self

from ocp_resources.pod import Pod
from ocp_utilities.exceptions import CommandExecFailed
Expand Down Expand Up @@ -32,7 +33,7 @@ def server_ip(self) -> str:
return self._server_ip

@abstractmethod
def __enter__(self) -> "BaseTcpClient":
def __enter__(self) -> Self:
pass

@abstractmethod
Expand Down Expand Up @@ -70,7 +71,7 @@ def __init__(
self._cmd += f" --bind {bind_ip}" if bind_ip else ""
self._cmd += f" --bind-dev {bind_dev}" if bind_dev else ""

def __enter__(self) -> "TcpServer":
def __enter__(self) -> Self:
self._vm.console(
commands=[f"{self._cmd} &"],
timeout=_DEFAULT_CMD_TIMEOUT_SEC,
Expand Down Expand Up @@ -121,7 +122,7 @@ def __init__(
self._cmd += f" --bind-dev {bind_dev}" if bind_dev else ""
self._cmd += f" --set-mss {maximum_segment_size}" if maximum_segment_size else ""

def __enter__(self) -> "VMTcpClient":
def __enter__(self) -> Self:
self._vm.console(
commands=[f"{self._cmd} &"],
timeout=_DEFAULT_CMD_TIMEOUT_SEC,
Expand Down Expand Up @@ -190,7 +191,7 @@ def __init__(
self._container = container or _IPERF_BIN
self._cmd += f" --bind {bind_interface}" if bind_interface else ""

def __enter__(self) -> "PodTcpClient":
def __enter__(self) -> Self:
# run the command in the background using nohup to ensure it keeps running after the exec session ends
self._pod.execute(
command=["sh", "-c", f"nohup {self._cmd} >/tmp/{_IPERF_BIN}.log 2>&1 &"], container=self._container
Expand Down Expand Up @@ -220,7 +221,7 @@ def active_tcp_connections(
client_vm: BaseVirtualMachine,
server_vm: BaseVirtualMachine,
iface_name: str,
) -> Generator[list[tuple[VMTcpClient, TcpServer]], None, None]:
) -> Generator[list[tuple[VMTcpClient, TcpServer]]]:
"""Start iperf3 client-server connections for all IPs on the server's interface.
The helper assumed the ip addresses are up.

Expand Down Expand Up @@ -258,7 +259,7 @@ def client_server_active_connection(
port: int = IPERF_SERVER_PORT,
maximum_segment_size: int = 0,
ip_family: int = 4,
) -> Generator[tuple[VMTcpClient, TcpServer], None, None]:
) -> Generator[tuple[VMTcpClient, TcpServer]]:
"""Start iperf3 client-server connection with continuous TCP traffic flow.

Automatically starts an iperf3 server and client, with traffic flowing continuously
Expand Down
2 changes: 1 addition & 1 deletion libs/storage/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, name: str):
self.name = name
self.storage_config = self.get_storage_config()

def supported_storage_classes(self) -> list["StorageClass"]:
def supported_storage_classes(self) -> list[StorageClass]:
return [
StorageClass(
name=StorageClassNames.CEPH_RBD_VIRTUALIZATION,
Expand Down
13 changes: 12 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ output-format = "grouped"
exclude = [".git", ".venv", ".mypy_cache", ".tox", "__pycache__"]

[tool.ruff.lint]
extend-select = ["PLC0415"]
extend-select = [
"PLC0415", # import-outside-top-level
"N802", # function name should be lowercase — method overrides from stdlib
"N815", # mixedCase variable in class scope — k8s API field names use camelCase
]
# TODO: Each ignored rule below should be addressed in a dedicated PR.
ignore = [
"SIM102", # collapsible-if — nested ifs are often more readable
Expand All @@ -32,11 +36,18 @@ ignore = [
"B023", # loop variable not bound in function — needs careful refactor
"G201", # .error(exc_info=True) vs .exception()
"SIM115", # context manager for file opening — may need structural changes
"SIM118", # in-dict-keys — k8s resource fields require explicit .keys() (not plain dicts)
"PERF102", # incorrect-dict-iterator — k8s resource fields require explicit .keys()/.items()
"B026", # star-arg unpacking after keyword arg — required when wrapping TimeoutSampler
]

[tool.ruff.lint.per-file-ignores]
# F821: undefined name — global_config files use dynamic exec() loading via pytest_testconfig
"tests/global_config*.py" = ["F821"]
# N802: ast.NodeVisitor method overrides use camelCase (visit_ImportFrom, etc.)
"scripts/tests_analyzer/pytest_marker_analyzer.py" = ["N802"]
# N802: logging.Formatter.formatTime override
"utilities/logger.py" = ["N802"]

[tool.ruff.lint.isort]
order-by-type = true
Expand Down
5 changes: 1 addition & 4 deletions scripts/quarantine_stats/generate_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1615,10 +1615,7 @@ def _generate_quarantined_details_by_version(self) -> str:
all_tab_buttons: list[str] = []
all_tab_contents: list[str] = []
first_tab = True
repo_index = 0

for _, version_stats_list in self.repo_stats.items():
repo_index += 1
for repo_index, (_, version_stats_list) in enumerate(self.repo_stats.items(), start=1):
repo_id = f"repo{repo_index}"

for version_stat in version_stats_list:
Expand Down
15 changes: 4 additions & 11 deletions scripts/tests_analyzer/pytest_marker_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,14 +815,12 @@ def _is_type_checking_guard(node: ast.If) -> bool:
if isinstance(test, ast.Name) and test.id == "TYPE_CHECKING":
return True
# ``if typing.TYPE_CHECKING:``
if (
return (
isinstance(test, ast.Attribute)
and isinstance(test.value, ast.Name)
and test.value.id == "typing"
and test.attr == "TYPE_CHECKING"
):
return True
return False
)


class FixtureVisitor(ast.NodeVisitor):
Expand Down Expand Up @@ -1779,12 +1777,7 @@ def _extract_modified_symbols(
# or potentially impactful executable code.
if line_number <= len(source_lines):
line_content = source_lines[line_number - 1].strip()
if (
not line_content
or line_content.startswith("#")
or line_content.startswith(("import ", "from "))
or line_content.startswith(('"""', "'''", '"', "'"))
):
if not line_content or line_content.startswith(("#", "import ", "from ", '"""', "'''", '"', "'")):
has_unattributed = True
else:
# Executable module-level code — conservative fallback
Expand Down Expand Up @@ -2010,7 +2003,7 @@ def _analyze_single_test_dependencies(
to_visit = []

for dep_file in current_level:
if dep_file in visited or not dep_file.suffix == ".py":
if dep_file in visited or dep_file.suffix != ".py":
continue

visited.add(dep_file)
Expand Down
1 change: 0 additions & 1 deletion tests/chaos/oadp/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def rebooted_vm_source_node(rhel_vm_with_dv_running, oadp_backup_in_progress, wo

LOGGER.info(f"Waiting for node {vm_node.name} to come back online")
wait_for_node_status(node=vm_node, status=True, wait_timeout=TIMEOUT_10MIN)
return


@pytest.fixture()
Expand Down
6 changes: 3 additions & 3 deletions tests/chaos/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import threading
import time
from contextlib import contextmanager
from datetime import datetime
from datetime import UTC, datetime

from kubernetes.dynamic.exceptions import ResourceNotFoundError
from ocp_resources.daemonset import DaemonSet
Expand Down Expand Up @@ -139,7 +139,7 @@ def _monitor_nginx_server(
timeout_watch = TimeoutWatch(timeout=_sampling_duration)
while timeout_watch.remaining_time() > 0:
if not is_http_ok(utility_pods=_utility_pods, node=_control_plane_host_node, url=_url):
raise Exception("Wrong status code from server.")
raise RuntimeError(f"HTTP health check failed for URL {_url}: expected status 200 (OK).")
time.sleep(_sampling_interval)
LOGGER.info("HTTP querying finished successfully.")

Expand Down Expand Up @@ -238,7 +238,7 @@ def collect_cluster_health_info(client, hco_namespace, additional_namespaces):

log_content = json.dumps(
{
f"{datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S')}": [
f"{datetime.now(tz=UTC).strftime('%Y/%m/%d %H:%M:%S')}": [
pods_status,
deployments_replicas,
daemonset_replicas,
Expand Down
5 changes: 1 addition & 4 deletions tests/deprecated_api/test_deprecation_audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ def skip_component_check(user_agent, deprecation_version):
return True

# Skip if deprecated version is greater than DEPRECATED_API_MAX_VERSION
if Version(deprecation_version) > Version(DEPRECATED_API_MAX_VERSION):
return True

return False
return Version(deprecation_version) > Version(DEPRECATED_API_MAX_VERSION)


def failure_not_in_component_list(component, annotations, audit_log_entry_dict):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ def data_sources_managed_by_data_import_crons_scope_function(

@pytest.fixture()
def data_sources_names_from_templates_scope_function(base_templates):
return set([
return {
get_parameters_from_template(template=template, parameter_subset=DATA_SOURCE_NAME)[DATA_SOURCE_NAME]
for template in base_templates
])
}


@pytest.fixture()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def get_all_dic_volume_names(client: DynamicClient, namespace: str) -> list[str]
list[str]: Combined list of PVC and VolumeSnapshot names managed by DataImportCron.
"""

def _fetch_volume_names(resource_cls: type[PersistentVolumeClaim] | type[VolumeSnapshot]) -> list[str]:
def _fetch_volume_names(resource_cls: type[PersistentVolumeClaim | VolumeSnapshot]) -> list[str]:
return [
volume.name
for volume in resource_cls.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def vm_cluster_preferences_expected_list():

@pytest.mark.polarion("CNV-9981")
def test_base_preferences_common_annotation(base_vm_cluster_preferences, vm_cluster_preferences_expected_list):
assert set([preference.name for preference in base_vm_cluster_preferences]) == set(
assert {preference.name for preference in base_vm_cluster_preferences} == set(
vm_cluster_preferences_expected_list
), "Not all base CNV cluster preferences exist"

Expand Down
8 changes: 5 additions & 3 deletions tests/infrastructure/vm_console_proxy/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import logging
from typing import Any, Type
from typing import Any

import requests
from kubernetes.dynamic import DynamicClient
Expand Down Expand Up @@ -56,11 +56,13 @@ def create_vnc_console_token(
response.raise_for_status() # Raise HTTPError for bad responses <4xx><5xx>
return response.json()["token"]
except requests.RequestException as exp:
logging.error(f"Request error occurred: {exp}")
LOGGER.error(f"Request error occurred: {exp}")
raise


def get_vm_console_proxy_resource(resource_kind: Type, client: DynamicClient, namespace: str | None = None) -> Type:
def get_vm_console_proxy_resource(
resource_kind: type[Resource], client: DynamicClient, namespace: str | None = None
) -> Resource:
if namespace:
vm_console_proxy_resource_object = resource_kind(
name=VM_CONSOLE_PROXY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_hco_overriding_apiserver_crypto_policy(
conflicting_resources = {
resource.kind: crypto_policy
for resource, crypto_policy in sample.items()
if expected_all_managed_crs_crypto_policies[resource] != sample[resource]
if expected_all_managed_crs_crypto_policies[resource] != crypto_policy
}
assert not conflicting_resources, (
"API server crypto policy overrides HCO crypto policy\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def updated_cr_with_custom_crypto_policy(
hco_namespace=hco_namespace,
expected_conditions={
**DEFAULT_HCO_CONDITIONS,
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
yield {"resource": resource, "tls_policy": value}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def csv_permissions(admin_client):

@pytest.mark.polarion("CNV-9805")
def test_new_operator_in_csv(operators_from_csv):
assert sorted(list(operators_from_csv)) == sorted(CNV_OPERATORS), (
assert sorted(operators_from_csv) == sorted(CNV_OPERATORS), (
f"Expected cnv operators:{CNV_OPERATORS} does not match operators {operators_from_csv} "
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_cdi_json_patch(
admin_client=admin_client,
hco_namespace=hco_namespace,
expected_conditions={
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
validate_cdi_json_patch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_cnao_json_patch(
admin_client=admin_client,
hco_namespace=hco_namespace,
expected_conditions={
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
cnao_spec = cnao_resource.instance.spec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_kubevirt_json_patch(
admin_client=admin_client,
hco_namespace=hco_namespace,
expected_conditions={
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
validate_kubevirt_json_patch(kubevirt_resource=kubevirt_resource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def test_multiple_json_patch(
admin_client=admin_client,
hco_namespace=hco_namespace,
expected_conditions={
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
validate_cdi_json_patch(
Expand All @@ -110,13 +110,13 @@ def test_multiple_json_patch_metrics(self, prometheus, kubevirt_all_unsafe_modif
)
for component in [COMPONENT_CDI, COMPONENT_KUBEVIRT]
}
for component_name in component_metrics_dict:
for component_name, previous_value in component_metrics_dict.items():
LOGGER.info(f"Waiting for metrics: {QUERY_STRING} for component: {component_name}")
wait_for_metrics_value_update(
prometheus=prometheus,
component_name=component_name,
query_string=QUERY_STRING,
previous_value=component_metrics_dict[component_name],
previous_value=previous_value,
)

@pytest.mark.polarion("CNV-8813")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_ssp_json_patch(
admin_client=admin_client,
hco_namespace=hco_namespace,
expected_conditions={
**{"TaintedConfiguration": Resource.Condition.Status.TRUE},
"TaintedConfiguration": Resource.Condition.Status.TRUE,
},
)
ssp_replicas_current_value = ssp_resource_scope_function.instance.spec.templateValidator.replicas
Expand Down
Loading
Loading