diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e534c22ad0a..aceedf38249 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -75,7 +75,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.7.4 + rev: v0.8.0 hooks: # Run the linter. - id: ruff @@ -213,7 +213,7 @@ repos: additional_dependencies: ['Jinja2>=3.0.0', 'cryptography>=38.0.4', 'deepmerge>=1.1.0'] - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.42.0 + rev: v0.43.0 hooks: - id: markdownlint name: Check for Linting errors on Markdown files with settings defined in `.github/.markdownlint.yaml`. diff --git a/ansible_collections/arista/avd/plugins/action/eos_cli_config_gen.py b/ansible_collections/arista/avd/plugins/action/eos_cli_config_gen.py index 6b8824b10b4..a6189973833 100644 --- a/ansible_collections/arista/avd/plugins/action/eos_cli_config_gen.py +++ b/ansible_collections/arista/avd/plugins/action/eos_cli_config_gen.py @@ -179,14 +179,14 @@ def prepare_task_vars(self, task_vars: dict, structured_config_filename: str, *, task_vars.update(read_vars(structured_config_filename)) # Read ansible variables and perform templating to support inline jinja2 - for var in task_vars: + for var, value in task_vars.items(): # TODO: - reevaluate these variables if str(var).startswith(("ansible", "molecule", "hostvars", "vars", "avd_switch_facts")): continue - if self._templar.is_template(task_vars[var]): + if self._templar.is_template(value): # Var contains a jinja2 template. try: - task_vars[var] = self._templar.template(task_vars[var], fail_on_undefined=False) + task_vars[var] = self._templar.template(value, fail_on_undefined=False) except Exception as e: msg = f"Exception during templating of task_var '{var}': '{e}'" raise AnsibleActionFail(msg) from e diff --git a/ansible_collections/arista/avd/plugins/modules/inventory_to_container.py b/ansible_collections/arista/avd/plugins/modules/inventory_to_container.py index d7defeb515c..5052441da1f 100644 --- a/ansible_collections/arista/avd/plugins/modules/inventory_to_container.py +++ b/ansible_collections/arista/avd/plugins/modules/inventory_to_container.py @@ -195,7 +195,7 @@ def get_configlet(src_folder: str = "", prefix: str = "AVD", extension: str = "c for file in src_configlets: # Build structure only if configlet match device_filter. if is_in_filter(hostname=file.stem, hostname_filter=device_filter): - name = prefix + "_" + file.stem if prefix != "none" else file.stem + name = f"{prefix}_{file.stem}" if prefix != "none" else file.stem with file.open(encoding="utf8") as stream: data = stream.read() configlets[name] = data @@ -222,10 +222,10 @@ def get_device_option_value(device_data_dict: dict, option_name: str) -> str | N Value set for variable, else None """ if is_iterable(device_data_dict): - for option in device_data_dict: - if option_name == option: - return device_data_dict[option] - return None + return next( + (value for option, value in device_data_dict.items() if option_name == option), + None, + ) return None diff --git a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/__init__.py b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/__init__.py index f7dd61937ce..939e1d5f7a9 100644 --- a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/__init__.py +++ b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/__init__.py @@ -9,4 +9,4 @@ from .md_report import MDReport from .results_manager import ResultsManager -__all__ = ["AnsibleEOSDevice", "get_anta_results", "AvdTestBase", "MDReport", "CSVReport", "ResultsManager", "ConfigManager"] +__all__ = ["AnsibleEOSDevice", "AvdTestBase", "CSVReport", "ConfigManager", "MDReport", "ResultsManager", "get_anta_results"] diff --git a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py index b40c411f77d..f6dc614f4e4 100644 --- a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py +++ b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py @@ -11,7 +11,7 @@ from urllib.error import HTTPError from ansible.errors import AnsibleActionFail, AnsibleConnectionFailure -from ansible.module_utils.connection import ConnectionError +from ansible.module_utils.connection import ConnectionError as AnsibleConnectionError from ansible_collections.arista.avd.plugins.plugin_utils.pyavd_wrappers import RaiseOnUse @@ -169,7 +169,7 @@ async def refresh(self) -> None: except (AnsibleConnectionFailure, HTTPError) as e: message = "Failed to connect to device" anta_log_exception(e, message, logger) - except ConnectionError as e: + except AnsibleConnectionError as e: message = "Error while getting the device information" anta_log_exception(e, message, logger) else: diff --git a/ansible_collections/arista/avd/plugins/plugin_utils/utils/__init__.py b/ansible_collections/arista/avd/plugins/plugin_utils/utils/__init__.py index 4e95bbe4269..06e93ce527b 100644 --- a/ansible_collections/arista/avd/plugins/plugin_utils/utils/__init__.py +++ b/ansible_collections/arista/avd/plugins/plugin_utils/utils/__init__.py @@ -21,18 +21,18 @@ default = get = RaiseOnUse(ImportError(f"The 'arista.avd' collection requires the 'pyavd' Python library. Got import error {e}")) __all__ = [ - "compile_searchpath", - "get_templar", - "log_message", + "NoAliasDumper", "PythonToAnsibleContextFilter", "PythonToAnsibleHandler", - "NoAliasDumper", - "get_validated_path", - "get_validated_value", - "cprofile", "YamlDumper", "YamlLoader", + "compile_searchpath", + "cprofile", "default", "get", + "get_templar", + "get_validated_path", + "get_validated_value", + "log_message", "write_file", ] diff --git a/ansible_collections/arista/avd/roles/eos_validate_state/python_modules/tests/__init__.py b/ansible_collections/arista/avd/roles/eos_validate_state/python_modules/tests/__init__.py index 84b101df22b..7c9513ca7f2 100644 --- a/ansible_collections/arista/avd/roles/eos_validate_state/python_modules/tests/__init__.py +++ b/ansible_collections/arista/avd/roles/eos_validate_state/python_modules/tests/__init__.py @@ -12,21 +12,21 @@ from .avdtestsystem import AvdTestNTP, AvdTestReloadCause __all__ = [ - "AvdTestP2PIPReachability", - "AvdTestLoopback0Reachability", - "AvdTestLLDPTopology", - "AvdTestInbandReachability", + "AvdTestAPIHttpsSSL", + "AvdTestAvtPath", + "AvdTestAvtRole", + "AvdTestBGP", + "AvdTestDpsReachability", "AvdTestHardware", + "AvdTestIPSecurity", + "AvdTestInbandReachability", + "AvdTestInterfacesState", + "AvdTestLLDPTopology", + "AvdTestLoopback0Reachability", "AvdTestMLAG", "AvdTestNTP", + "AvdTestP2PIPReachability", "AvdTestReloadCause", - "AvdTestInterfacesState", "AvdTestRoutingTable", - "AvdTestBGP", - "AvdTestAPIHttpsSSL", "AvdTestStun", - "AvdTestIPSecurity", - "AvdTestDpsReachability", - "AvdTestAvtPath", - "AvdTestAvtRole", ] diff --git a/pyproject.toml b/pyproject.toml index ba69d6b4ee8..f638f8ad74b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,8 +19,6 @@ target-version = "py310" [tool.ruff.lint] extend-select = ["ALL"] ignore = [ - "ANN101", # Missing type annotation for `self` in method - we know what self is.. - "ANN102", # Missing type annotation for `cls` in classmethod - we know what cls is.. "D203", # Ignoring conflicting D* warnings - one-blank-line-before-class "D212", # Ignoring conflicting D* warnings - multi-line-summary-first-line "COM812", # Ignoring conflicting rules that may cause conflicts when used with the formatter diff --git a/python-avd/pyavd/__init__.py b/python-avd/pyavd/__init__.py index e9898530e1d..fa3b46bc504 100644 --- a/python-avd/pyavd/__init__.py +++ b/python-avd/pyavd/__init__.py @@ -21,6 +21,7 @@ __version__ = "5.1.0" __all__ = [ + "ValidationResult", "get_avd_facts", "get_device_config", "get_device_doc", @@ -28,5 +29,4 @@ "get_fabric_documentation", "validate_inputs", "validate_structured_config", - "ValidationResult", ] diff --git a/python-avd/pyavd/_cv/client/exceptions.py b/python-avd/pyavd/_cv/client/exceptions.py index 06afa9bf4ff..92847c10894 100644 --- a/python-avd/pyavd/_cv/client/exceptions.py +++ b/python-avd/pyavd/_cv/client/exceptions.py @@ -3,18 +3,19 @@ # that can be found in the LICENSE file. from __future__ import annotations -from asyncio.exceptions import TimeoutError -from re import compile, fullmatch +from asyncio.exceptions import TimeoutError as AsyncioTimeoutError +from re import compile as re_compile +from re import fullmatch from grpclib.const import Status from grpclib.exceptions import GRPCError -MSG_SIZE_EXCEEDED_REGEX = compile(r"grpc: received message larger than max \((?P\d+) vs\. (?P\d+)\)") +MSG_SIZE_EXCEEDED_REGEX = re_compile(r"grpc: received message larger than max \((?P\d+) vs\. (?P\d+)\)") def get_cv_client_exception(exception: Exception, cv_client_details: str | None = None) -> Exception | None: """ - Convert GRPCError or TimeoutError instances to an instance of the relevant subclass of CVClientException. + Convert GRPCError or AsyncioTimeoutError instances to an instance of the relevant subclass of CVClientException. Parameters: exception: Exception to convert. @@ -33,7 +34,7 @@ def get_cv_client_exception(exception: Exception, cv_client_details: str | None new_exception.max_size = int(matches.group("max")) new_exception.size = int(matches.group("size")) return new_exception - if isinstance(exception, TimeoutError): + if isinstance(exception, AsyncioTimeoutError): return CVTimeoutError(cv_client_details, *exception.args) # Last resort return None so calling exception handling can just raise the single error instead of a chain. diff --git a/python-avd/pyavd/_cv/client/versioning.py b/python-avd/pyavd/_cv/client/versioning.py index bd752b39bf8..acde860cb8c 100644 --- a/python-avd/pyavd/_cv/client/versioning.py +++ b/python-avd/pyavd/_cv/client/versioning.py @@ -1,12 +1,13 @@ # Copyright (c) 2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. -from re import compile, fullmatch +from re import compile as re_compile +from re import fullmatch from .constants import CVAAS_VERSION_STRING # The double braces are escaping braces for the f-string. The regex pattern will get a single brace. -VERSION_PATTERN = compile(rf"(\d{{4}}\.\d{{1,2}}\.\d{{1,2}}|{CVAAS_VERSION_STRING})") +VERSION_PATTERN = re_compile(rf"(\d{{4}}\.\d{{1,2}}\.\d{{1,2}}|{CVAAS_VERSION_STRING})") class CvVersion: diff --git a/python-avd/pyavd/_utils/__init__.py b/python-avd/pyavd/_utils/__init__.py index fb17ba5c445..b3bddca35d9 100644 --- a/python-avd/pyavd/_utils/__init__.py +++ b/python-avd/pyavd/_utils/__init__.py @@ -31,13 +31,13 @@ "batch", "compare_dicts", "default", + "get", "get_all", "get_all_with_path", "get_indices_of_duplicate_items", "get_ip_from_ip_prefix", "get_ip_from_pool", "get_item", - "get", "get_v2", "groupby", "groupby_obj", diff --git a/python-avd/schema_tools/metaschema/meta_schema_model.py b/python-avd/schema_tools/metaschema/meta_schema_model.py index 4ffb87562cd..70b7d78a5b0 100644 --- a/python-avd/schema_tools/metaschema/meta_schema_model.py +++ b/python-avd/schema_tools/metaschema/meta_schema_model.py @@ -441,7 +441,7 @@ def _descendant_tables(self) -> set[str]: return descendant_tables - def model_post_init(self, __context: Any) -> None: + def model_post_init(self, context: Any) -> None: """ Overrides BaseModel.model_post_init. @@ -473,7 +473,7 @@ def model_post_init(self, __context: Any) -> None: else: self.items._is_first_list_key = True - return super().model_post_init(__context) + return super().model_post_init(context) class AvdSchemaDict(AvdSchemaBaseModel): @@ -552,7 +552,7 @@ def _descendant_tables(self) -> set[str]: return descendant_tables - def model_post_init(self, __context: Any) -> None: + def model_post_init(self, context: Any) -> None: """ Overrides BaseModel.model_post_init. @@ -572,7 +572,7 @@ def model_post_init(self, __context: Any) -> None: childschema._key = f"<{key}>" childschema._parent_schema = self - return super().model_post_init(__context) + return super().model_post_init(context) class AristaAvdSchema(AvdSchemaDict): diff --git a/python-avd/tests/pyavd/j2filters/test_default.py b/python-avd/tests/pyavd/j2filters/test_default.py index 56abad50161..668ffccb0de 100644 --- a/python-avd/tests/pyavd/j2filters/test_default.py +++ b/python-avd/tests/pyavd/j2filters/test_default.py @@ -17,7 +17,7 @@ class TestDefaultFilter: @pytest.mark.parametrize("default_value", DEFAULT_VALUE_LIST) def test_default(self, primary_value: Any, default_value: Any) -> None: resp = default(primary_value, *default_value) - if isinstance(primary_value, Undefined) or primary_value is None and len(DEFAULT_VALUE_LIST) >= 1: + if isinstance(primary_value, Undefined) or (primary_value is None and len(DEFAULT_VALUE_LIST) >= 1): for i in default_value: if isinstance(i, Undefined) or i is None or i == "": continue