diff --git a/python/ironic-understack/ironic_understack/redfish_inspect_understack.py b/python/ironic-understack/ironic_understack/redfish_inspect_understack.py index dd575e505..63785e7e9 100644 --- a/python/ironic-understack/ironic_understack/redfish_inspect_understack.py +++ b/python/ironic-understack/ironic_understack/redfish_inspect_understack.py @@ -9,9 +9,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -""" -Redfish Inspect Interface modified for Understack -""" +"""Redfish Inspect Interface modified for Understack.""" import re @@ -23,10 +21,11 @@ from ironic.drivers.modules.inspect_utils import get_inspection_data from ironic.drivers.modules.redfish.inspect import RedfishInspect from ironic.drivers.redfish import RedfishHardware -from ironic_understack.conf import CONF from oslo_log import log from oslo_utils import units +from ironic_understack.conf import CONF + LOG = log.getLogger(__name__) FLAVORS = FlavorSpec.from_directory(CONF.ironic_understack.flavors_dir) LOG.info(f"Loaded {len(FLAVORS)} flavor specifications.") @@ -111,10 +110,8 @@ def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) patched_ifaces = RedfishHardware().supported_inspect_interfaces patched_ifaces.append(UnderstackDracRedfishInspect) - setattr( - RedfishHardware, - "supported_inspect_interfaces", - property(lambda _: patched_ifaces), + RedfishHardware.supported_inspect_interfaces = property( + lambda _: patched_ifaces ) @@ -123,8 +120,4 @@ def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) patched_ifaces = IDRACHardware().supported_inspect_interfaces patched_ifaces.append(UnderstackDracRedfishInspect) - setattr( - IDRACHardware, - "supported_inspect_interfaces", - property(lambda _: patched_ifaces), - ) + IDRACHardware.supported_inspect_interfaces = property(lambda _: patched_ifaces) diff --git a/python/ironic-understack/ironic_understack/resource_class.py b/python/ironic-understack/ironic_understack/resource_class.py index 3f5955c9f..08785789b 100644 --- a/python/ironic-understack/ironic_understack/resource_class.py +++ b/python/ironic-understack/ironic_understack/resource_class.py @@ -1,12 +1,14 @@ # from ironic.drivers.modules.inspector.hooks import base -from ironic.common import exception -from ironic.drivers.modules.inspector.hooks import base -from ironic_understack.conf import CONF +import re + from flavor_matcher.flavor_spec import FlavorSpec from flavor_matcher.machine import Machine from flavor_matcher.matcher import Matcher +from ironic.common import exception +from ironic.drivers.modules.inspector.hooks import base from oslo_log import log as logging -import re + +from ironic_understack.conf import CONF LOG = logging.getLogger(__name__) @@ -23,7 +25,6 @@ class UndercloudResourceClassHook(base.InspectionHook): def __call__(self, task, inventory, plugin_data): """Update node resource_class with deducted flavor.""" - try: memory_mb = inventory["memory"]["physical_mb"] disk_size_gb = int(int(inventory["disks"][0]["size"]) / 10**9) @@ -60,7 +61,9 @@ def __call__(self, task, inventory, plugin_data): f"Inventory has missing hardware information for node {task.node.uuid}." ) LOG.error(msg) - raise exception.InvalidNodeInventory(node=task.node.uuid, reason=msg) + raise exception.InvalidNodeInventory( + node=task.node.uuid, reason=msg + ) from None except NoMatchError: msg = f"No matching flavor found for {task.node.uuid}" LOG.error(msg) diff --git a/python/ironic-understack/pyproject.toml b/python/ironic-understack/pyproject.toml index 65a2ed6d5..11810bae6 100644 --- a/python/ironic-understack/pyproject.toml +++ b/python/ironic-understack/pyproject.toml @@ -1,3 +1,7 @@ +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + [tool.poetry] name = "ironic-understack" version = "0.0.0" @@ -10,8 +14,9 @@ packages = [ ] [tool.poetry.dependencies] -ironic = ">=24.1" +# keep this python field in sync with the tool.ruff.target-version python = "^3.10" +ironic = ">=24.1" pyyaml = "^6.0" understack-flavor-matcher = {path = "../understack-flavor-matcher"} @@ -20,10 +25,6 @@ pytest = "^8.3.2" pytest-github-actions-annotate-failures = "*" pytest-cov = "^5.0.0" -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - [tool.poetry.plugins."ironic.inspection.hooks"] "resource-class" = "ironic_understack.resource_class:UndercloudResourceClassHook" @@ -44,9 +45,35 @@ fix = true [tool.ruff.lint] select = [ + "D", # pydocstyle + "E", # pycodestyle (error) + "F", # pyflakes + "B", # flake8-bugbear + "I", # isort "S", # flake8-bandit + "UP", # pyupgrade + "ASYNC", # flake8-async +] + +ignore = [ + "D100", # don't require docs for every module + "D101", # don't require docs for every class + "D102", # don't require docs for every class method + "D103", # don't require docs for every function + "D104", # don't require docs for every package + "D106", # don't require docs for every nested class + "D107", # don't require docs for __init__ + "D417" # don't require docs for every function parameter ] +[tool.ruff.lint.isort] +force-single-line = true + + +[tool.ruff.lint.pydocstyle] +# enable the google doc style rules by default +convention = "google" + [tool.ruff.lint.per-file-ignores] "ironic_understack/tests/*.py" = [ "S101", # allow 'assert' for pytest diff --git a/python/neutron-understack/neutron_understack/neutron_understack_mech.py b/python/neutron-understack/neutron_understack/neutron_understack_mech.py index 1a595d870..8abb5a02c 100644 --- a/python/neutron-understack/neutron_understack/neutron_understack_mech.py +++ b/python/neutron-understack/neutron_understack/neutron_understack_mech.py @@ -6,12 +6,10 @@ import neutron_lib.api.definitions.portbindings as portbindings from neutron_lib import constants as p_const from neutron_lib.plugins.ml2 import api -from neutron_lib.plugins.ml2.api import ( - MechanismDriver, - NetworkContext, - PortContext, - SubnetContext, -) +from neutron_lib.plugins.ml2.api import MechanismDriver +from neutron_lib.plugins.ml2.api import NetworkContext +from neutron_lib.plugins.ml2.api import PortContext +from neutron_lib.plugins.ml2.api import SubnetContext from oslo_config import cfg from neutron_understack import config diff --git a/python/neutron-understack/neutron_understack/tests/test_neutron_understack_mech.py b/python/neutron-understack/neutron_understack/tests/test_neutron_understack_mech.py index 6f632a870..b646b965a 100644 --- a/python/neutron-understack/neutron_understack/tests/test_neutron_understack_mech.py +++ b/python/neutron-understack/neutron_understack/tests/test_neutron_understack_mech.py @@ -1,5 +1,6 @@ import json -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock +from unittest.mock import patch import pytest diff --git a/python/neutron-understack/pyproject.toml b/python/neutron-understack/pyproject.toml index f9299a3ff..1887ae5f6 100644 --- a/python/neutron-understack/pyproject.toml +++ b/python/neutron-understack/pyproject.toml @@ -23,11 +23,8 @@ classifiers = [ "Programming Language :: Python :: 3.10", ] -[tool.ruff] -target-version = "py310" -fix = true - [tool.poetry.dependencies] +# keep this python field in sync with the tool.ruff.target-version python = "^3.10" requests = "^2" neutron-lib = "^3" @@ -42,9 +39,9 @@ minversion = "6.0" addopts = "-ra" filterwarnings = "ignore::DeprecationWarning" - -[tool.isort] -profile = "open_stack" +[tool.ruff] +target-version = "py310" +fix = true [tool.ruff.lint] select = [ @@ -64,9 +61,14 @@ ignore = [ "D102", # don't require docs for every class method "D103", # don't require docs for every function "D104", # don't require docs for every package + "D106", # don't require docs for every nested class + "D107", # don't require docs for __init__ "D417" # don't require docs for every function parameter ] +[tool.ruff.lint.isort] +force-single-line = true + [tool.ruff.lint.pydocstyle] # enable the google doc style rules by default convention = "google" diff --git a/python/understack-flavor-matcher/flavor_matcher/flavor_spec.py b/python/understack-flavor-matcher/flavor_matcher/flavor_spec.py index b79699082..cf16c3452 100644 --- a/python/understack-flavor-matcher/flavor_matcher/flavor_spec.py +++ b/python/understack-flavor-matcher/flavor_matcher/flavor_spec.py @@ -3,6 +3,7 @@ from dataclasses import dataclass import yaml + from flavor_matcher.machine import Machine @@ -50,7 +51,7 @@ def baremetal_nova_resource_class(self): @property def memory_mib(self): - """Returns memory size in MiB""" + """Returns memory size in MiB.""" return self.memory_gb * 1024 @staticmethod @@ -61,7 +62,7 @@ def from_directory(directory: str = "/etc/flavors/") -> list["FlavorSpec"]: if filename.endswith(".yaml") or filename.endswith(".yml"): filepath = os.path.join(root, filename) try: - with open(filepath, "r") as file: + with open(filepath) as file: yaml_content = file.read() flavor_spec = FlavorSpec.from_yaml(yaml_content) flavor_specs.append(flavor_spec) @@ -97,11 +98,13 @@ def score_machine(self, machine: Machine): ): return 100 - # Rule 2: If machine has less memory than specified in the flavor, it cannot be used + # Rule 2: If machine has less memory than specified in the + # flavor, it cannot be used if machine.memory_gb < self.memory_gb: return 0 - # Rule 3: If machine has smaller disk than specified in the flavor, it cannot be used + # Rule 3: If machine has smaller disk than specified in the + # flavor, it cannot be used if any(machine.disk_gb < drive for drive in self.drives): return 0 diff --git a/python/understack-flavor-matcher/flavor_matcher/matcher.py b/python/understack-flavor-matcher/flavor_matcher/matcher.py index 5e009f31b..fac5be3be 100644 --- a/python/understack-flavor-matcher/flavor_matcher/matcher.py +++ b/python/understack-flavor-matcher/flavor_matcher/matcher.py @@ -1,5 +1,5 @@ -from flavor_matcher.machine import Machine from flavor_matcher.flavor_spec import FlavorSpec +from flavor_matcher.machine import Machine class Matcher: @@ -7,9 +7,7 @@ def __init__(self, flavors: list[FlavorSpec]): self.flavors = flavors def match(self, machine: Machine) -> list[FlavorSpec]: - """ - Find list of all flavors that the machine is eligible for. - """ + """Find list of all flavors that the machine is eligible for.""" results = [] for flavor in self.flavors: score = flavor.score_machine(machine) @@ -18,11 +16,11 @@ def match(self, machine: Machine) -> list[FlavorSpec]: return results def pick_best_flavor(self, machine: Machine) -> FlavorSpec | None: - """ - Obtains list of all flavors that particular machine can be classified - as, then tries to select "the best" one. - """ + """Selects the best patching flavor. + Obtains list of all flavors that particular machine can be classified as, + then tries to select "the best" one. + """ possible = self.match(machine) if len(possible) == 0: diff --git a/python/understack-flavor-matcher/pyproject.toml b/python/understack-flavor-matcher/pyproject.toml index 09a9a91e7..5eb1fd2b1 100644 --- a/python/understack-flavor-matcher/pyproject.toml +++ b/python/understack-flavor-matcher/pyproject.toml @@ -1,3 +1,7 @@ +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + [tool.poetry] name = "understack-flavor-matcher" version = "0.0.0" @@ -10,6 +14,7 @@ packages = [ ] [tool.poetry.dependencies] +# keep this python field in sync with the tool.ruff.target-version python = "^3.10" pyyaml = "^6.0" @@ -18,13 +23,48 @@ pytest = "^8.3.2" pytest-github-actions-annotate-failures = "*" pytest-cov = "^5.0.0" -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - [tool.pytest.ini_options] minversion = "6.0" addopts = "-ra --cov=flavor_matcher" testpaths = [ "tests", ] + +[tool.ruff] +target-version = "py310" +fix = true + +[tool.ruff.lint] +select = [ + "D", # pydocstyle + "E", # pycodestyle (error) + "F", # pyflakes + "B", # flake8-bugbear + "I", # isort + "S", # flake8-bandit + "UP", # pyupgrade + "ASYNC", # flake8-async +] + +ignore = [ + "D100", # don't require docs for every module + "D101", # don't require docs for every class + "D102", # don't require docs for every class method + "D103", # don't require docs for every function + "D104", # don't require docs for every package + "D106", # don't require docs for every nested class + "D107", # don't require docs for __init__ + "D417" # don't require docs for every function parameter +] + +[tool.ruff.lint.isort] +force-single-line = true + +[tool.ruff.lint.pydocstyle] +# enable the google doc style rules by default +convention = "google" + +[tool.ruff.lint.per-file-ignores] +"tests/**/*.py" = [ + "S101", # allow 'assert' for pytest +] diff --git a/python/understack-flavor-matcher/tests/test_flavor_spec.py b/python/understack-flavor-matcher/tests/test_flavor_spec.py index f0b5af755..f158f6bd8 100644 --- a/python/understack-flavor-matcher/tests/test_flavor_spec.py +++ b/python/understack-flavor-matcher/tests/test_flavor_spec.py @@ -3,6 +3,7 @@ from unittest.mock import patch import pytest + from flavor_matcher.flavor_spec import FlavorSpec from flavor_matcher.machine import Machine @@ -56,7 +57,7 @@ def test_from_yaml(valid_yaml): def test_from_yaml_invalid(invalid_yaml): - with pytest.raises(Exception): + with pytest.raises(Exception): # noqa:B017 FlavorSpec.from_yaml(invalid_yaml) @@ -312,7 +313,8 @@ def test_cpu_model_not_exact_but_memory_and_disk_match(flavors): def test_large_flavor_memory_slightly_less_disk_exact(flavors): - # Machine with slightly less memory than required for the medium flavor, exact disk space + # Machine with slightly less memory than required for the medium + # flavor, exact disk space machine = Machine( memory_mb=204600, cpu="Intel 80386DX", disk_gb=1800, model="Dell XPS1319" ) diff --git a/python/understack-flavor-matcher/tests/test_matcher.py b/python/understack-flavor-matcher/tests/test_matcher.py index 452008849..fd0189e7e 100644 --- a/python/understack-flavor-matcher/tests/test_matcher.py +++ b/python/understack-flavor-matcher/tests/test_matcher.py @@ -1,4 +1,5 @@ import pytest + from flavor_matcher.flavor_spec import FlavorSpec from flavor_matcher.machine import Machine from flavor_matcher.matcher import Matcher diff --git a/python/understack-workflows/pyproject.toml b/python/understack-workflows/pyproject.toml index 231e65f05..ca0d4ac29 100644 --- a/python/understack-workflows/pyproject.toml +++ b/python/understack-workflows/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ ] [tool.poetry.dependencies] +# keep this python field in sync with the tool.ruff.target-version python = "~3.11.0" pydantic = "^2" @@ -66,9 +67,6 @@ filterwarnings = [ target-version = "py311" fix = true -[tool.isort] -profile = "open_stack" - [tool.ruff.lint] select = [ "D", # pydocstyle