Skip to content

Commit

Permalink
Merge branch 'main' into setuptools
Browse files Browse the repository at this point in the history
  • Loading branch information
devon-mar committed Jun 24, 2024
2 parents 538df8f + e50db1b commit b93ecf4
Show file tree
Hide file tree
Showing 10 changed files with 3,740 additions and 3,628 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ jobs:
run: poetry install
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'

- name: Run pylama
run: make pylama
- name: Run ruff
run: make ruff
- name: Run black
run: make black
- name: Run mypy
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ The Black GitHub repo has information about how you can integrate Black in your

Tests
-------------
As part of the automatic CI on every pull request, besides coding style checks with ``black``, we also do linting with ``pylama``, static type checking with ``mypy``, unit tests with ``pytest``, docs generation with ``sphinx`` and ``nbsphinx`` (for Jupyter notebooks) and verification of outputs in Jupyter notebook tutorials with pytest plugin ``nbval``.
As part of the automatic CI on every pull request, besides coding style checks with ``black``, we also do linting with ``ruff``, static type checking with ``mypy``, unit tests with ``pytest``, docs generation with ``sphinx`` and ``nbsphinx`` (for Jupyter notebooks) and verification of outputs in Jupyter notebook tutorials with pytest plugin ``nbval``.

After modifying any code in the core, at first, we recommend running unit tests locally before running the whole test suite (which takes longer time):

Expand Down
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ sphinx:
# poetry run sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html
echo "WARNING: sphinx needs to be added here!!!"

.PHONY: pylama
pylama:
poetry run pylama ${NORNIR_DIRS}

.PHONY: mypy
mypy:
poetry run mypy nornir tests
Expand All @@ -39,8 +35,12 @@ nbval:
docs/tutorial/ \
docs/howto/

.PHONY: ruff
ruff:
poetry run ruff check .

.PHONY: tests
tests: black pylama mypy nbval pytest sphinx
tests: ruff black mypy nbval pytest sphinx

.PHONY: docker-tests
docker-tests: docker
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Only latest version is supported.

## Reporting a Vulnerability

To report a vulnerability feel free to reach out on [slack](https://github.com/nornir-automation/nornir#contact--support) so we can fix before a public disclosure.
To report a vulnerability feel free to reach out privately on [GitHub](https://github.com/nornir-automation/nornir/security/advisories/new) so we can fix before a public disclosure.
If the issue is on a dependency feel free to open a PR bumping such depdency without contacting us first.
58 changes: 37 additions & 21 deletions nornir/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import logging
import logging.config
import types
from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, List, Optional, Type
from typing import 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
from nornir.core.state import GlobalState
from nornir.core.task import AggregatedResult, Task

if TYPE_CHECKING:
from nornir.core.inventory import Host # noqa: W0611

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -46,7 +44,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
Expand All @@ -62,16 +60,18 @@ def __exit__(
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.
assigned to the copy. The original 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.
assigned to the copy. The original 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":
"""
Expand All @@ -80,16 +80,16 @@ 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

def run(
self,
task,
raise_on_error=None,
on_good=True,
on_failed=False,
task: Callable[..., Any],
raise_on_error: Optional[bool] = None,
on_good: bool = True,
on_failed: bool = False,
name: Optional[str] = None,
**kwargs: Any,
) -> AggregatedResult:
Expand All @@ -111,15 +111,15 @@ def run(
Returns:
:obj:`nornir.core.task.AggregatedResult`: results of each execution
"""
task = Task(
run_task = Task(
task,
self,
global_dry_run=self.data.dry_run,
name=name,
processors=self.processors,
**kwargs,
)
self.processors.task_started(task)
self.processors.task_started(run_task)

run_on = []
if on_good:
Expand All @@ -135,14 +135,14 @@ def run(
if num_hosts:
logger.info(
"Running task %r with args %s on %d hosts",
task.name,
run_task.name,
kwargs,
num_hosts,
)
else:
logger.warning("Task %r has not been run – 0 hosts selected", task.name)
logger.warning("Task %r has not been run – 0 hosts selected", run_task.name)

result = self.runner.run(task, run_on)
result = self.runner.run(run_task, run_on)

raise_on_error = (
raise_on_error
Expand All @@ -154,7 +154,7 @@ def run(
else:
self.data.failed_hosts.update(result.failed_hosts.keys())

self.processors.task_completed(task, result)
self.processors.task_completed(run_task, result)

return result

Expand All @@ -163,11 +163,27 @@ def dict(self) -> Dict[str, Any]:
return {"data": self.data.dict(), "inventory": self.inventory.dict()}

def close_connections(self, on_good: bool = True, on_failed: bool = False) -> None:
def close_connections_task(task):
def close_connections_task(task: Task) -> None:
task.host.close_connections()

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")

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
Expand Down
10 changes: 0 additions & 10 deletions nornir/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,24 @@ class ConnectionAlreadyOpen(ConnectionException):
Raised when opening an already opened connection
"""

pass


class ConnectionNotOpen(ConnectionException):
"""
Raised when trying to close a connection that isn't open
"""

pass


class PluginAlreadyRegistered(Exception):
"""
Raised when trying to register an already registered plugin
"""

pass


class PluginNotRegistered(Exception):
"""
Raised when trying to access a plugin that is not registered
"""

pass


class NornirExecutionError(Exception):
"""
Expand Down Expand Up @@ -96,8 +88,6 @@ class NornirNoValidInventoryError(Exception):
Raised by nornir when :meth:`nornir.plugins.inventory.parse` fails to load any valid inventory
"""

pass


class ConflictingConfigurationWarning(UserWarning):
pass
3 changes: 0 additions & 3 deletions nornir/core/plugins/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,15 @@ def open(
Connect to the device and populate the attribute :attr:`connection` with
the underlying connection
"""
pass

def close(self) -> None:
"""Close the connection with the device"""
pass

@property
def connection(self) -> Any:
"""
Established connection
"""
pass


ConnectionPluginRegister: PluginRegister[Type[ConnectionPlugin]] = PluginRegister(
Expand Down
Loading

0 comments on commit b93ecf4

Please sign in to comment.