From a996af8fc06359c46a34837a8e665bd83ca332bc Mon Sep 17 00:00:00 2001 From: Mohammad Torkashvand <mohammad.torkashvand@geant.org> Date: Mon, 29 Apr 2024 12:02:00 +0200 Subject: [PATCH] fix ruff errors --- gso/__init__.py | 2 +- gso/schedules/scheduling.py | 33 ++++++++++++++----------- gso/schedules/task_vacuum.py | 4 +-- gso/schedules/validate_products.py | 4 +-- gso/schedules/validate_subscriptions.py | 4 +-- gso/services/infoblox.py | 2 +- gso/utils/shared_enums.py | 11 ++++++--- gso/worker.py | 2 +- pyproject.toml | 3 +++ setup.py | 2 ++ test/auth/test_oidc_policy_helper.py | 4 +-- test/conftest.py | 2 +- test/schedules/test_scheduling.py | 30 ++++++++++++---------- test/utils/test_helpers.py | 4 +-- test/workflows/__init__.py | 3 ++- 15 files changed, 65 insertions(+), 45 deletions(-) diff --git a/gso/__init__.py b/gso/__init__.py index 94c8f5fa..ecdfd940 100644 --- a/gso/__init__.py +++ b/gso/__init__.py @@ -28,7 +28,7 @@ def init_worker_app() -> OrchestratorCore: def init_cli_app() -> typer.Typer: """Initialise :term:`GSO` as a CLI application.""" - from gso.cli import imports, netbox + from gso.cli import imports, netbox # noqa: PLC0415 cli_app.add_typer(imports.app, name="import-cli") cli_app.add_typer(netbox.app, name="netbox-cli") diff --git a/gso/schedules/scheduling.py b/gso/schedules/scheduling.py index 2e83fab3..b0e22a09 100644 --- a/gso/schedules/scheduling.py +++ b/gso/schedules/scheduling.py @@ -7,16 +7,21 @@ from typing import Any from celery import current_app from celery.schedules import crontab +from pydantic import BaseModel -def scheduler( - name: str, - minute: str = "*", - hour: str = "*", - day_of_week: str = "*", - day_of_month: str = "*", - month_of_year: str = "*", -) -> Callable[[Callable], Callable]: +class CronScheduleConfig(BaseModel): + """Configuration for scheduling a task using crontab-like timing parameters.""" + + name: str + minute: str = "*" + hour: str = "*" + day_of_week: str = "*" + day_of_month: str = "*" + month_of_year: str = "*" + + +def scheduler(cron_scheduler_config: CronScheduleConfig) -> Callable[[Callable], Callable]: """Schedule a Celery task using crontab-like timing. Examples @@ -44,14 +49,14 @@ def scheduler( task_path = f"{module.__name__}.{task_func.__name__}" current_app.conf.beat_schedule[task_func.__name__] = { - "name": name, + "name": cron_scheduler_config.name, "task": task_path, "schedule": crontab( - minute=minute, - hour=hour, - day_of_month=day_of_month, - month_of_year=month_of_year, - day_of_week=day_of_week, + minute=cron_scheduler_config.minute, + hour=cron_scheduler_config.hour, + day_of_month=cron_scheduler_config.day_of_month, + month_of_year=cron_scheduler_config.month_of_year, + day_of_week=cron_scheduler_config.day_of_week, ), } diff --git a/gso/schedules/task_vacuum.py b/gso/schedules/task_vacuum.py index 98e05343..be04380f 100644 --- a/gso/schedules/task_vacuum.py +++ b/gso/schedules/task_vacuum.py @@ -2,12 +2,12 @@ from orchestrator.services.processes import start_process -from gso.schedules.scheduling import scheduler +from gso.schedules.scheduling import CronScheduleConfig, scheduler from gso.worker import celery @celery.task -@scheduler(name="Clean up tasks", hour="*/6") +@scheduler(CronScheduleConfig(name="Clean up tasks", hour="*/6")) def vacuum_tasks() -> None: """Run all cleanup tasks every 6 hours.""" start_process("task_clean_up_tasks") diff --git a/gso/schedules/validate_products.py b/gso/schedules/validate_products.py index cb9ecc67..580c7540 100644 --- a/gso/schedules/validate_products.py +++ b/gso/schedules/validate_products.py @@ -2,13 +2,13 @@ from orchestrator.services.processes import start_process -from gso.schedules.scheduling import scheduler +from gso.schedules.scheduling import CronScheduleConfig, scheduler from gso.services.subscriptions import count_incomplete_validate_products from gso.worker import celery @celery.task -@scheduler(name="Validate Products and inactive subscriptions", minute="30", hour="2") +@scheduler(CronScheduleConfig(name="Validate Products and inactive subscriptions", minute="30", hour="2")) def validate_products() -> None: """Validate all products.""" if count_incomplete_validate_products() > 0: diff --git a/gso/schedules/validate_subscriptions.py b/gso/schedules/validate_subscriptions.py index 7c440435..9e79ec91 100644 --- a/gso/schedules/validate_subscriptions.py +++ b/gso/schedules/validate_subscriptions.py @@ -5,7 +5,7 @@ from orchestrator.services.processes import get_execution_context from orchestrator.services.subscriptions import TARGET_DEFAULT_USABLE_MAP, WF_USABLE_MAP from orchestrator.targets import Target -from gso.schedules.scheduling import scheduler +from gso.schedules.scheduling import CronScheduleConfig, scheduler from gso.services.subscriptions import get_insync_subscriptions from gso.worker import celery @@ -13,7 +13,7 @@ logger = structlog.get_logger(__name__) @celery.task -@scheduler(name="Subscriptions Validator", minute="10", hour="0") +@scheduler(CronScheduleConfig(name="Subscriptions Validator", minute="10", hour="0")) def validate_subscriptions() -> None: """Validate all subscriptions using their corresponding validation workflow.""" subscriptions = get_insync_subscriptions() diff --git a/gso/services/infoblox.py b/gso/services/infoblox.py index 514c55cb..874ee6f5 100644 --- a/gso/services/infoblox.py +++ b/gso/services/infoblox.py @@ -37,7 +37,7 @@ def _setup_connection() -> tuple[connector.Connector, IPAMParams]: return connector.Connector(options), oss -def _allocate_network( +def _allocate_network( # noqa: PLR0917 conn: connector.Connector, dns_view: str, network_view: str, diff --git a/gso/utils/shared_enums.py b/gso/utils/shared_enums.py index 1054876f..6a590515 100644 --- a/gso/utils/shared_enums.py +++ b/gso/utils/shared_enums.py @@ -1,13 +1,18 @@ """Shared choices for the different models.""" import ipaddress -from typing import Annotated +from typing import Annotated, Any from pydantic import Field, PlainSerializer from pydantic_forms.types import strEnum from typing_extensions import Doc +def convert_to_str(value: Any) -> str: + """Convert the value to a string.""" + return str(value) + + class Vendor(strEnum): """Enumerator for the different product vendors that are supported.""" @@ -29,11 +34,11 @@ PortNumber = Annotated[ IPv4AddressType = Annotated[ - ipaddress.IPv4Address, PlainSerializer(lambda ip: str(ip), return_type=str, when_used="always") + ipaddress.IPv4Address, PlainSerializer(convert_to_str, return_type=str, when_used="always") ] IPv6AddressType = Annotated[ - ipaddress.IPv6Address, PlainSerializer(lambda ip: str(ip), return_type=str, when_used="always") + ipaddress.IPv6Address, PlainSerializer(convert_to_str, return_type=str, when_used="always") ] diff --git a/gso/worker.py b/gso/worker.py index b1a3db2c..b2abfe6f 100644 --- a/gso/worker.py +++ b/gso/worker.py @@ -9,7 +9,7 @@ from gso.settings import load_oss_params class OrchestratorCelery(Celery): """A :term:`GSO` instance that functions as a Celery worker.""" - def on_init(self) -> None: + def on_init(self) -> None: # noqa: PLR6301 """Initialise a new Celery worker.""" init_worker_app() diff --git a/pyproject.toml b/pyproject.toml index 34c2cc10..376371b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,3 +113,6 @@ filterwarnings = [ "ignore", "default:::gso", ] +[tool.ruff.lint.per-file-ignores] +"test/*" = ["PLR0917", "S101", "D104", "D105", "D103", "D100", "ARG001", "D102", "PLR2004", "D101", "D106", "D107", "PLR0914", "PLC0415", "PLC2701"] +"gso/workflows/*" = ["PLR0917", "PLR0914"] \ No newline at end of file diff --git a/setup.py b/setup.py index 08fa01b8..6339e95a 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +"""Setup script for the GÉANT Service Orchestrator.""" + from setuptools import find_packages, setup setup( diff --git a/test/auth/test_oidc_policy_helper.py b/test/auth/test_oidc_policy_helper.py index 767e3442..46b934ca 100644 --- a/test/auth/test_oidc_policy_helper.py +++ b/test/auth/test_oidc_policy_helper.py @@ -268,7 +268,7 @@ async def test_oidc_user_call_no_token(oidc_user, mock_request): mock_post.return_value = MagicMock(status_code=200, json=lambda: {"active": False}) mock_get.return_value = MagicMock(status_code=200, json=dict) - result = await oidc_user.__call__(mock_request) + result = await oidc_user.__call__(mock_request) # noqa: PLC2801 assert result is None @@ -281,7 +281,7 @@ async def test_oidc_user_call_token_from_request(oidc_user, mock_request, mock_a oidc_user.introspect_token = AsyncMock(return_value={"active": True}) oidc_user.userinfo = AsyncMock(return_value=OIDCUserModel({"sub": "123", "name": "John Doe"})) - result = await oidc_user.__call__(mock_request) + result = await oidc_user.__call__(mock_request) # noqa: PLC2801 assert isinstance(result, OIDCUserModel) assert result["sub"] == "123" diff --git a/test/conftest.py b/test/conftest.py index a5d42798..8fae41e7 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -57,7 +57,7 @@ def pytest_collection_modifyitems(config, items): class UseJuniperSide(strEnum): - """Define on tests on which side to use Juniper router""" + """Define on tests on which side to use Juniper router.""" NONE = "none" SIDE_A = "side_a" diff --git a/test/schedules/test_scheduling.py b/test/schedules/test_scheduling.py index 82168eb4..17811174 100644 --- a/test/schedules/test_scheduling.py +++ b/test/schedules/test_scheduling.py @@ -3,7 +3,7 @@ from unittest.mock import MagicMock, patch import pytest from orchestrator.targets import Target -from gso.schedules.scheduling import scheduler +from gso.schedules.scheduling import CronScheduleConfig, scheduler @pytest.fixture(scope="module") @@ -42,12 +42,14 @@ def test_scheduler_updates_beat_schedule(mock_celery): mock_celery.conf.beat_schedule = {} @scheduler( - name="A cool task", - minute="0", - hour="0", - day_of_week="*", - day_of_month="*", - month_of_year="*", + CronScheduleConfig( + name="A cool task", + minute="0", + hour="0", + day_of_week="*", + day_of_month="*", + month_of_year="*", + ) ) def mock_task(): return "task result" @@ -64,12 +66,14 @@ def test_scheduled_task_still_works(): """Ensure that the scheduler decorator does not change the behavior of the function it decorates.""" @scheduler( - name="A cool task", - minute="0", - hour="0", - day_of_week="*", - day_of_month="*", - month_of_year="*", + CronScheduleConfig( + name="A cool task", + minute="0", + hour="0", + day_of_week="*", + day_of_month="*", + month_of_year="*", + ) ) def mock_task(): return "task result" diff --git a/test/utils/test_helpers.py b/test/utils/test_helpers.py index 5dee0aa8..e80e6f30 100644 --- a/test/utils/test_helpers.py +++ b/test/utils/test_helpers.py @@ -23,7 +23,7 @@ def mock_netbox_client(): @pytest.fixture() def generate_tt_numbers(faker, request): - """Generator for valid and invalid tt numbers.""" + """Get a Generator for valid and invalid tt numbers.""" valid_count = request.param.get("valid", 0) invalid_count = request.param.get("invalid", 0) @@ -78,7 +78,7 @@ def test_nokia_router_with_interfaces_returns_choice(mock_router, mock_netbox_cl @pytest.mark.parametrize("generate_tt_numbers", [{"valid": 5, "invalid": 3}], indirect=True) def test_tt_number(generate_tt_numbers): - """Test different TT numbers""" + """Test different TT numbers.""" for tt_number, is_valid in generate_tt_numbers: if is_valid: assert validate_tt_number(tt_number) == tt_number diff --git a/test/workflows/__init__.py b/test/workflows/__init__.py index 246d2b76..b44bace9 100644 --- a/test/workflows/__init__.py +++ b/test/workflows/__init__.py @@ -157,7 +157,8 @@ class WorkflowInstanceForTests(LazyWorkflowInstance): This can be as simple as merely importing a workflow function. However, if it concerns a workflow generating function, that function will be called with or without arguments as specified. - Returns: + Returns + ------- A workflow function. """ -- GitLab