From 46ecb53f2d167939b942ea02a1ae8dd09b8ed48b Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sat, 8 Jun 2024 09:59:06 +0200 Subject: [PATCH 1/2] Add property for optional runner --- nornir/core/__init__.py | 10 +++++++++- setup.cfg | 1 - 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index eaa63c83..8dbf1fd2 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, List, Optional, Type from nornir.core.configuration import Config +from nornir.core.exceptions import PluginNotRegistered from nornir.core.inventory import Inventory from nornir.core.plugins.runners import RunnerPlugin from nornir.core.processor import Processor, Processors @@ -142,7 +143,7 @@ def run( else: logger.warning("Task %r has not been run – 0 hosts selected", task.name) - result = self.runner.run(task, run_on) + result = self._runner.run(task, run_on) raise_on_error = ( raise_on_error @@ -168,6 +169,13 @@ def close_connections_task(task): self.run(task=close_connections_task, on_good=on_good, on_failed=on_failed) + @property + def _runner(self) -> RunnerPlugin: + if self.runner: + return self.runner + + raise PluginNotRegistered("Runner plugin not registered") + @classmethod def get_validators(cls) -> Generator[Callable[["Nornir"], "Nornir"], None, None]: yield cls.validate diff --git a/setup.cfg b/setup.cfg index bc69f979..656cba83 100644 --- a/setup.cfg +++ b/setup.cfg @@ -48,7 +48,6 @@ warn_redundant_casts = True [mypy-nornir.core] disallow_untyped_defs = False disallow_incomplete_defs = False -strict_optional = False [mypy-tests.*] ignore_errors = True From ce52022fadfe8ebeee7fab886b4d13b071f10302 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Tue, 11 Jun 2024 19:20:47 +0200 Subject: [PATCH 2/2] Add method to clone parameters with private attribute --- nornir/core/__init__.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 8dbf1fd2..76e83772 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -47,7 +47,7 @@ def __init__( self.inventory = inventory self.config = config or Config() self.processors = processors or Processors() - self.runner = runner + self._runner = runner def __enter__(self) -> "Nornir": return self @@ -65,14 +65,16 @@ def with_processors(self, processors: List[Processor]) -> "Nornir": Given a list of Processor objects return a copy of the nornir object with the processors assigned to the copy. The orinal object is left unmodified. """ - return Nornir(**{**self.__dict__, **{"processors": Processors(processors)}}) + return Nornir( + **{**self._clone_parameters(), **{"processors": Processors(processors)}} + ) def with_runner(self, runner: RunnerPlugin) -> "Nornir": """ Given a runner return a copy of the nornir object with the runner assigned to the copy. The orinal object is left unmodified. """ - return Nornir(**{**self.__dict__, **{"runner": runner}}) + return Nornir(**{**self._clone_parameters(), **{"runner": runner}}) def filter(self, *args: Any, **kwargs: Any) -> "Nornir": """ @@ -81,7 +83,7 @@ def filter(self, *args: Any, **kwargs: Any) -> "Nornir": Returns: :obj:`Nornir`: A new object with same configuration as ``self`` but filtered inventory. """ - b = Nornir(**self.__dict__) + b = Nornir(**self._clone_parameters()) b.inventory = self.inventory.filter(*args, **kwargs) return b @@ -143,7 +145,7 @@ def run( else: logger.warning("Task %r has not been run – 0 hosts selected", task.name) - result = self._runner.run(task, run_on) + result = self.runner.run(task, run_on) raise_on_error = ( raise_on_error @@ -170,12 +172,21 @@ def close_connections_task(task): self.run(task=close_connections_task, on_good=on_good, on_failed=on_failed) @property - def _runner(self) -> RunnerPlugin: - if self.runner: - return self.runner + def runner(self) -> RunnerPlugin: + if self._runner: + return self._runner raise PluginNotRegistered("Runner plugin not registered") + def _clone_parameters(self) -> Dict[str, Any]: + return { + "data": self.data, + "inventory": self.inventory, + "config": self.config, + "processors": self.processors, + "runner": self._runner, + } + @classmethod def get_validators(cls) -> Generator[Callable[["Nornir"], "Nornir"], None, None]: yield cls.validate