From e6050ad44bc68b7ec1e71190c989c1e2c61faa2b Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 19 Dec 2024 11:12:24 -0600 Subject: [PATCH 1/4] chore(ironic-understack): fix lint issues --- .../redfish_inspect_understack.py | 19 ++++++------------- .../ironic_understack/resource_class.py | 15 +++++++++------ 2 files changed, 15 insertions(+), 19 deletions(-) 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) From 89d818127aa9de17650e3a4a159e277d6510ff17 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 19 Dec 2024 11:24:36 -0600 Subject: [PATCH 2/4] chore(neutron-understack): fix lint issues --- .../neutron_understack/neutron_understack_mech.py | 10 ++++------ .../tests/test_neutron_understack_mech.py | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) 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 From 5020fd8874ba6c4b868f589e25ee2de0c444975f Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 19 Dec 2024 11:32:54 -0600 Subject: [PATCH 3/4] chore(understack-flavor-matcher): fix lint issues --- .../flavor_matcher/flavor_spec.py | 11 +++++++---- .../flavor_matcher/matcher.py | 14 ++++++-------- .../tests/test_flavor_spec.py | 6 ++++-- .../tests/test_matcher.py | 1 + 4 files changed, 18 insertions(+), 14 deletions(-) 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/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 From 4ffb090c8f7eba1815611fbbcf98f960b60ab9f2 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 19 Dec 2024 11:02:55 -0600 Subject: [PATCH 4/4] chore(python): get our ruff rules in sync Get all of our ruff rules in sync between our projects. Moved some other sections to line up the same. Got rid of the old isort we don't use. --- python/ironic-understack/pyproject.toml | 37 ++++++++++++-- python/neutron-understack/pyproject.toml | 16 ++++--- .../understack-flavor-matcher/pyproject.toml | 48 +++++++++++++++++-- python/understack-workflows/pyproject.toml | 4 +- 4 files changed, 86 insertions(+), 19 deletions(-) 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/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/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-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