From 1165f243c7ea55f441f2a628468a60d7ae6b4f33 Mon Sep 17 00:00:00 2001 From: David Mahler Date: Fri, 31 May 2024 03:20:24 -0400 Subject: [PATCH 01/50] Fix typo tertiary --> Secondary (#908) --- docs/howto/filtering_deep_dive.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/howto/filtering_deep_dive.ipynb b/docs/howto/filtering_deep_dive.ipynb index 94dd038a..389d55b1 100644 --- a/docs/howto/filtering_deep_dive.ipynb +++ b/docs/howto/filtering_deep_dive.ipynb @@ -1242,7 +1242,7 @@ "print(\"=\" * 50)\n", "\n", "\n", - "# Use Case 3 - filter hosts by site_type of tertiary\n", + "# Use Case 3 - filter hosts by site_type of secondary\n", "# Assign site_type of secondary to variable for later usage\n", "site_type=\"secondary\"\n", "# Execute filter based on site_type\n", From 3bafdd98d7788b0d71d5706a9efc9bd95c6844a6 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sat, 8 Jun 2024 17:29:11 +0200 Subject: [PATCH 02/50] Fix CI (#914) --- .github/workflows/main.yaml | 11 +++++------ poetry.lock | 21 +++++---------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 436825de..8c924d88 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -55,7 +55,7 @@ jobs: strategy: matrix: python-version: [ '3.8', '3.9', '3.10', '3.11' ] - platform: [ubuntu-latest, macOS-latest, windows-latest] + platform: [ubuntu-latest, macos-13, windows-2019] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v2 @@ -63,7 +63,6 @@ jobs: uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - architecture: x64 - name: Install Poetry uses: snok/install-poetry@v1 @@ -78,7 +77,7 @@ jobs: with: path: .venv key: venv-${{ matrix.python-version }}-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} - if: ${{ matrix.platform != 'windows-latest' }} # windows hangs if using a cached venv + if: ${{ matrix.platform != 'windows-2019' }} # windows hangs if using a cached venv - name: Install Dependencies run: poetry install @@ -86,15 +85,15 @@ jobs: - name: Run pytest run: make pytest - if: ${{ matrix.platform != 'windows-latest' }} + if: ${{ matrix.platform != 'windows-2019' }} - name: Run pytest run: poetry run pytest --cov=nornir --cov-report=term-missing - if: ${{ matrix.platform == 'windows-latest' }} + if: ${{ matrix.platform == 'windows-2019' }} - name: Run nbval run: make nbval - if: ${{ matrix.platform != 'windows-latest' }} + if: ${{ matrix.platform != 'windows-2019' }} # release: # name: Releasing to pypi diff --git a/poetry.lock b/poetry.lock index 1ec1cbff..0a65e523 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alabaster" @@ -715,13 +715,13 @@ test = ["pytest (>=6)"] [[package]] name = "executing" -version = "2.0.0" +version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "executing-2.0.0-py2.py3-none-any.whl", hash = "sha256:06df6183df67389625f4e763921c6cf978944721abf3e714000200aab95b0657"}, - {file = "executing-2.0.0.tar.gz", hash = "sha256:0ff053696fdeef426cda5bd18eacd94f82c91f49823a2e9090124212ceea9b08"}, + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, ] [package.extras] @@ -1496,16 +1496,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2490,7 +2480,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, From a4aa92a4ff487633df4cb8a302311b8fb8620f84 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sat, 8 Jun 2024 20:52:21 +0200 Subject: [PATCH 03/50] Upgrade GitHub actions (#916) --- .github/workflows/main.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8c924d88..e39906d2 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -11,9 +11,9 @@ jobs: platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup python - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: x64 @@ -26,7 +26,7 @@ jobs: virtualenvs-in-project: true - name: Cache Poetry virtualenv - uses: actions/cache@v2 + uses: actions/cache@v4 id: cached-poetry-dependencies with: path: .venv @@ -58,9 +58,9 @@ jobs: platform: [ubuntu-latest, macos-13, windows-2019] runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup python - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -72,7 +72,7 @@ jobs: virtualenvs-in-project: true - name: Cache Poetry virtualenv - uses: actions/cache@v2 + uses: actions/cache@v4 id: cached-poetry-dependencies with: path: .venv From f96d3e733beed63fcbb09f6db96ef1a3e9437da8 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Tue, 11 Jun 2024 19:44:59 +0200 Subject: [PATCH 04/50] Fix typos in core docstrings (#923) --- nornir/core/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index eaa63c83..91df6cd8 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -62,14 +62,14 @@ 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)}}) 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}}) From 9b8aa7bb5e47b7f75f0b34f04596f43985169a2f Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Wed, 12 Jun 2024 03:16:23 +0200 Subject: [PATCH 05/50] Remove unused Host import (#922) --- nornir/core/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 91df6cd8..0eec15f6 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -1,7 +1,7 @@ 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.inventory import Inventory @@ -10,9 +10,6 @@ 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__) From 123909f1880079928edc542ebfb4d15ffd486249 Mon Sep 17 00:00:00 2001 From: David Barroso Date: Wed, 12 Jun 2024 10:11:35 +0200 Subject: [PATCH 06/50] Update SECURITY.md (#921) --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index acf80696..c390d4e6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -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. From 93f93399c17bc3c62aa47bbc95d0ac3e0677ac97 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 14 Jun 2024 16:15:47 +0200 Subject: [PATCH 07/50] Add property for optional runner (#913) * Add property for optional runner * Add method to clone parameters with private attribute --------- Co-authored-by: David Barroso --- nornir/core/__init__.py | 27 +++++++++++++++++++++++---- setup.cfg | 1 - 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 0eec15f6..18f9c618 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -4,6 +4,7 @@ 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 @@ -43,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 @@ -61,14 +62,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 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 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": """ @@ -77,7 +80,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 @@ -165,6 +168,22 @@ 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") + + 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 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 3de5d380abc38d18ef05981c008847ee8d57f6bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:33:37 +0200 Subject: [PATCH 08/50] Bump urllib3 from 2.0.7 to 2.2.2 (#925) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.7 to 2.2.2. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.0.7...2.2.2) --- updated-dependencies: - dependency-name: urllib3 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0a65e523..41c06c57 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -1496,6 +1496,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2480,6 +2490,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3435,18 +3446,18 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.0.7" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] From a013a99f06d725bf32b53496b710a62655918e5b Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Wed, 19 Jun 2024 14:05:50 +0200 Subject: [PATCH 09/50] Fix remaining type-hints (#924) Also renamed the "task" variable within run() as that was shadowing the argument for "task" Co-authored-by: David Barroso --- nornir/core/__init__.py | 22 +++++++++++----------- setup.cfg | 4 ---- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 18f9c618..b30f17b7 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -86,10 +86,10 @@ def filter(self, *args: Any, **kwargs: Any) -> "Nornir": 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: @@ -111,7 +111,7 @@ 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, @@ -119,7 +119,7 @@ def run( processors=self.processors, **kwargs, ) - self.processors.task_started(task) + self.processors.task_started(run_task) run_on = [] if on_good: @@ -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 @@ -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 @@ -163,7 +163,7 @@ 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) diff --git a/setup.cfg b/setup.cfg index 656cba83..3fd76670 100644 --- a/setup.cfg +++ b/setup.cfg @@ -45,9 +45,5 @@ warn_unused_ignores = True warn_return_any = True warn_redundant_casts = True -[mypy-nornir.core] -disallow_untyped_defs = False -disallow_incomplete_defs = False - [mypy-tests.*] ignore_errors = True From e8e6e3b6346b7ae364fea351fef895c2940bebb1 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 24 Jun 2024 12:18:29 +0200 Subject: [PATCH 10/50] Add linting with ruff (#926) --- .github/workflows/main.yaml | 2 + Makefile | 6 +- poetry.lock | 41 +++++--- pyproject.toml | 197 ++++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index e39906d2..dd2af198 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -36,6 +36,8 @@ jobs: run: poetry install if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + - name: Run ruff + run: make ruff - name: Run pylama run: make pylama - name: Run black diff --git a/Makefile b/Makefile index dfb3a201..926484af 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,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 pylama mypy nbval pytest sphinx .PHONY: docker-tests docker-tests: docker diff --git a/poetry.lock b/poetry.lock index 41c06c57..cd4edb99 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alabaster" @@ -1496,16 +1496,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2490,7 +2480,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2923,6 +2912,32 @@ files = [ {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, ] +[[package]] +name = "ruff" +version = "0.4.9" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.4.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991"}, + {file = "ruff-0.4.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db"}, + {file = "ruff-0.4.9-py3-none-win32.whl", hash = "sha256:8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521"}, + {file = "ruff-0.4.9-py3-none-win_amd64.whl", hash = "sha256:e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52"}, + {file = "ruff-0.4.9-py3-none-win_arm64.whl", hash = "sha256:5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198"}, + {file = "ruff-0.4.9.tar.gz", hash = "sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3"}, +] + [[package]] name = "scp" version = "0.14.5" @@ -3557,4 +3572,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "f35aad317156cd103cf142bd44370d03acf384480d011837c473afbb59e6da21" +content-hash = "d8b67ba6327d7b9cca180438dec2e6bef065b33084e62873a426c59110f354fc" diff --git a/pyproject.toml b/pyproject.toml index 1ffc46fd..71fdc3c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,7 @@ types-pkg-resources = "^0.1.3" nornir-jinja2 = "0.2.0" nornir-utils = "0.2.0" nornir-napalm = "0.4.0" +ruff = "^0.4.9" [tool.poetry.group.docs.dependencies] sphinx = "6.2.1" @@ -56,3 +57,199 @@ nbsphinx = "0.9.2" pygments = "2.16.1" sphinx-issues = "3.0.1" +[tool.ruff] +line-length = 100 + +[tool.ruff.lint] +preview = true + +select = [ + "A", # flake8-builtins + "AIR", # Airflow + "ANN", # flake8-annotations + "ARG", # flake8-unused-arguments + "ASYNC", # flake8-async + "B", # flake8-bugbear + "BLE", # flake8-blind-except + "C4", # flake8-comprehensions + "C90", # mccabe complexity + "COM", # flake8-commas + "DJ", # flake8-django + "DTZ", # flake8-datetimez + "E", # pycodestyle errors + "ERA", # eradicate + "EXE", # flake8-executable + "F", # pyflakes + "FBT", # flake8-boolean-trap + "FIX", # flake8-fixme + "FLY", # flynt + "FURB", # refurb + "I", # isort-like checks + "ICN", # flake8-import-conventions + "LOG", # flake8-logging + "INP", # flake8-no-pep420 + "INT", # flake8-gettext + "ISC", # flake8-implicit-str-concat + "G", # flake8-logging-format + "N", # pep8-naming + "NPY", # NumPy-specific rules + "PD", # pandas-vet + "PERF", # Perflint + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "PYI", # flake8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RSE", # flake8-raise + "RUF", # Ruff-specific rules + "S", # flake8-bandit + "SIM", # flake8-simplify + "SLF", # flake8-self + "SLOT", # flake8-slots + "TCH", # flake8-type-checking + "TD", # flake8-todos + "TRIO", # flake8-trio + "T10", # flake8-debugger + "T20", # flake8-print + "TID", # flake8-tidy-imports + "TRY", # tryceratops + "UP", # pyupgrade + "W", # pycodestyle warnings + "YTT", # flake8-2020 +] + +ignore = [ + "N801", # Class name should use CapWords convention + "N818", # Exception name should be named with an Error suffix +################################################################################################## +# The ignored rules below should be removed once the code has been updated, they are included # +# like this so that we can reactivate them one by one. Alternatively ignored after further # +# investigation if they are deemed to not make sense. # +################################################################################################## + "ANN204", # Missing return type annotation for special method `__init__` + "ANN401", # Dynamically typed expressions (typing.Any) are disallowed + "ARG002", # Unused method argument + "B028", # No explicit `stacklevel` keyword argument found + "C419", # Unnecessary list comprehension + "COM812", # Trailing comma missing + "ERA001", # Found commented-out code + "EXE001", # Shebang is present but file is not executable + "FBT001", # Boolean-typed positional argument in function definition + "FBT002", # Boolean default positional argument in function definition + "FURB101", # `open` and `read` should be replaced by `Path(filename).read_text()` + "INP001", # File is part of an implicit namespace package. Add an `__init__.py`. + "N804", # First argument of a class method should be named `cls` + "PERF203", # `try`-`except` within a loop incurs performance overhead + "PGH004", # Use specific rule codes when using `noqa` + "PIE790", # Unnecessary `pass` statement + "PIE800", # Unnecessary spread `**` + "PLC0205", # Class `__slots__` should be a non-string iterable + "PLC2801", # Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function + "PLR1704", # Redefining argument with the local name + "PLR6201", # Use a `set` literal when testing for membership + "PLR6301", # Method `run` could be a function, class method, or static method + "PLW1514", # `open` in text mode without explicit `encoding` argument + "PLW1641", # Object does not implement `__hash__` method + "PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()` + "PTH120", # `os.path.dirname()` should be replaced by `Path.parent` + "PTH123", # `open()` should be replaced by `Path.open()` + "PYI036", # The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None` + "RET505", # Unnecessary `else` after `return` statement + "RET504", # Unnecessary assignment before `return` statement + "RSE102", # Unnecessary parentheses on raised exception + "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "RUF023", # `__slots__` is not sorted + "RUF100", # Unused blanket `noqa` directive + "S701", # By default, jinja2 sets `autoescape` to `False`. Consider using `autoescape=True` or the `select_autoescape` function to mitigate XSS vulnerabilities. + "SLF001", # Private member accessed + "SIM108", # Use ternary operator `config = Config.from_file(config_file, **kwargs) if config_file else Config.from_dict(**kwargs)` instead of `if`-`else`-block + "SIM110", # Use `return any(g.name == group or g.has_parent_group(group) for g in self.groups)` instead of `for` loop + "TRY002", # Create your own exception + "TRY003", # Avoid specifying long messages outside the exception class + "TRY004", # Prefer `TypeError` exception for invalid type + "TRY300", # Consider moving this statement to an `else` block + "TRY400", # Use `logging.exception` instead of `logging.error` + "UP004", # Class inherits from `object` + "UP009", # UTF-8 encoding declaration is unnecessary + "UP015", # Unnecessary open mode parameters + "UP032", # Use f-string instead of `format` call + "UP034", # Avoid extraneous parentheses + "UP037", # Remove quotes from type annotation +] + +[tool.ruff.lint.mccabe] +max-complexity = 12 + + +[tool.ruff.lint.pylint] +max-args = 11 +max-branches = 16 +max-positional-args = 10 +max-public-methods = 22 +max-returns = 11 + +[tool.ruff.lint.per-file-ignores] + +"docs/conf.py" = [ + "A001", # Variable `copyright` is shadowing a Python builtin +] + +"docs/highlighter.py" = [ + "ANN001", # Missing type annotation for function argument + "ANN201", # Missing return type annotation for public function +] + +"nornir/core/configuration.py" = [ + "A002", # Argument `format` / `help` is shadowing a Python builtin +] + +"nornir/core/task.py" = [ + "BLE001", # Do not catch blind exception: `Exception` +] + +"nornir/init_nornir.py" = [ + "N802", # Function name `InitNornir` should be lowercase +] + +"tests/**.py" = [ + "BLE001", # Do not catch blind exception: `Exception` + "N802", # Function name should be lowercase + "S101", # Use of assert detected + "S105", # Possible hardcoded password assigned + +################################################################################################## +# The ignored rules below should be removed once the code has been updated, they are included # +# like this so that we can reactivate them one by one. Alternatively ignored after further # +# investigation if they are deemed to not make sense. # +################################################################################################## + "ANN001", # Missing type annotation for function argument + "ANN002", # Missing type annotation for `*args` + "ANN003", # Missing type annotation for `**kwargs` + "ANN201", # Missing return type annotation for public function + "ANN202", # Missing return type annotation for private function + "ANN206", # Missing return type annotation for classmethod + "ARG001", # Unused function argument + "B007", # Loop control variable `host` not used within loop body + "C414", # Unnecessary `list` call within `sorted()` + "DTZ005", # `datetime.datetime.now()` called without a `tz` argument + "LOG009", # Use of undocumented `logging.WARN` constant + "N999", # Invalid module name + "PLC1901", # Can be simplified as an empty string is falsey + "PLR0904", # Too many public methods + "PLR2004", # Magic value used in comparison, consider replacing with a constant variable + "PTH118", # `os.path.join()` should be replaced by `Path` with `/` operator + "PTH120", # `os.path.dirname()` should be replaced by `Path.parent` + "PT003", # `scope='function'` is implied in `@pytest.fixture()` + "PT004", # Fixture does not return anything, add leading underscore + "PT006", # Wrong type passed to first argument of `@pytest.mark.parametrize`; expected `tuple` + "PT012", # `pytest.raises()` block should contain a single simple statement + "PT018", # Assertion should be broken down into multiple parts + "PT011", # `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + "SIM118", # Use `key in dict` instead of `key in dict.keys()` + "SIM300", # Yoda conditions are discouraged +] + From 67448b2b0960af5f430e92c8551b6b70482ad8db Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 24 Jun 2024 18:14:43 +0200 Subject: [PATCH 11/50] Remove pylama (#928) --- .github/workflows/main.yaml | 2 - CONTRIBUTING.rst | 2 +- Makefile | 6 +-- poetry.lock | 79 +------------------------------------ pyproject.toml | 1 - setup.cfg | 19 --------- 6 files changed, 3 insertions(+), 106 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index dd2af198..2c899adc 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -38,8 +38,6 @@ jobs: - name: Run ruff run: make ruff - - name: Run pylama - run: make pylama - name: Run black run: make black - name: Run mypy diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2b7ae022..61a4ce16 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -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): diff --git a/Makefile b/Makefile index 926484af..f0b13e34 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -44,7 +40,7 @@ ruff: poetry run ruff check . .PHONY: tests -tests: ruff black pylama mypy nbval pytest sphinx +tests: ruff black mypy nbval pytest sphinx .PHONY: docker-tests docker-tests: docker diff --git a/poetry.lock b/poetry.lock index cd4edb99..b0fc3cf8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1542,17 +1542,6 @@ files = [ [package.dependencies] traitlets = "*" -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mistune" version = "3.0.2" @@ -2180,17 +2169,6 @@ files = [ [package.extras] tests = ["pytest"] -[[package]] -name = "pycodestyle" -version = "2.11.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, - {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, -] - [[package]] name = "pycparser" version = "2.21" @@ -2202,23 +2180,6 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - [[package]] name = "pyeapi" version = "1.0.2" @@ -2236,17 +2197,6 @@ netaddr = "*" dev = ["check-manifest", "pep8", "pyflakes", "twine"] test = ["coverage", "mock"] -[[package]] -name = "pyflakes" -version = "3.1.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, - {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, -] - [[package]] name = "pygments" version = "2.16.1" @@ -2261,33 +2211,6 @@ files = [ [package.extras] plugins = ["importlib-metadata"] -[[package]] -name = "pylama" -version = "8.4.1" -description = "Code audit tool for python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pylama-8.4.1-py3-none-any.whl", hash = "sha256:5bbdbf5b620aba7206d688ed9fc917ecd3d73e15ec1a89647037a09fa3a86e60"}, - {file = "pylama-8.4.1.tar.gz", hash = "sha256:2d4f7aecfb5b7466216d48610c7d6bad1c3990c29cdd392ad08259b161e486f6"}, -] - -[package.dependencies] -mccabe = ">=0.7.0" -pycodestyle = ">=2.9.1" -pydocstyle = ">=6.1.1" -pyflakes = ">=2.5.0" - -[package.extras] -all = ["eradicate", "mypy", "pylint", "radon", "vulture"] -eradicate = ["eradicate"] -mypy = ["mypy"] -pylint = ["pylint"] -radon = ["radon"] -tests = ["eradicate (>=2.0.0)", "mypy", "pylama-quotes", "pylint (>=2.11.1)", "pytest (>=7.1.2)", "pytest-mypy", "radon (>=5.1.0)", "toml", "types-setuptools", "types-toml", "vulture"] -toml = ["toml (>=0.10.2)"] -vulture = ["vulture"] - [[package]] name = "pynacl" version = "1.5.0" @@ -3572,4 +3495,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "d8b67ba6327d7b9cca180438dec2e6bef065b33084e62873a426c59110f354fc" +content-hash = "beeecfa098d80f15b4ab1fec20916e4f3972a1d5afbf7f0c13c6590926273a94" diff --git a/pyproject.toml b/pyproject.toml index 71fdc3c9..e6647c8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,6 @@ decorator = "*" nbval = "^0.10.0" pytest = "*" pytest-cov = "*" -pylama = "*" requests-mock = "*" black = "^23.9.1" isort = "^5.12.0" diff --git a/setup.cfg b/setup.cfg index 3fd76670..e538fc17 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,25 +4,6 @@ # will need to generate wheels for each Python version that you support. universal=1 -# E127: continuation line over-indented for visual indent -# E128: continuation line under-indented for visual indent -# E265: block comment should start with # -# E731: do not assign a lambda expression, use a def -# D10?: missing docstrings -[pylama] -linters = mccabe,pycodestyle,pyflakes -ignore = D203,C901,W503 -skip = .tox/*,.venv/*,nornir/_vendor/* - -[pylama:pycodestyle] -max_line_length = 100 - -[pycodestyle] -ignore = D203,C901,W503 -exclude = .git,__pycache__,build,dist -max-complexity = 10 -max-line-length = 100 - [tool:pytest] #addopts = --cov=nornir --cov-report=term-missing -vs filterwarnings = From e50db1bc0e82b6ef9c24e45378fe30daf226cb31 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 24 Jun 2024 18:42:57 +0200 Subject: [PATCH 12/50] Remove unnecessary `pass` statement (FIX: PIE790) (#929) --- nornir/core/exceptions.py | 10 ---------- nornir/core/plugins/connections.py | 3 --- pyproject.toml | 1 - 3 files changed, 14 deletions(-) diff --git a/nornir/core/exceptions.py b/nornir/core/exceptions.py index a5616faf..01599bb1 100644 --- a/nornir/core/exceptions.py +++ b/nornir/core/exceptions.py @@ -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): """ @@ -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 diff --git a/nornir/core/plugins/connections.py b/nornir/core/plugins/connections.py index f2324bdd..747a4e41 100644 --- a/nornir/core/plugins/connections.py +++ b/nornir/core/plugins/connections.py @@ -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( diff --git a/pyproject.toml b/pyproject.toml index e6647c8f..0b36460d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -143,7 +143,6 @@ ignore = [ "N804", # First argument of a class method should be named `cls` "PERF203", # `try`-`except` within a loop incurs performance overhead "PGH004", # Use specific rule codes when using `noqa` - "PIE790", # Unnecessary `pass` statement "PIE800", # Unnecessary spread `**` "PLC0205", # Class `__slots__` should be a non-string iterable "PLC2801", # Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function From ff2d26ee1b77de990de9878ea0ca06cb91aa1a33 Mon Sep 17 00:00:00 2001 From: devon-mar Date: Mon, 24 Jun 2024 13:56:18 -0700 Subject: [PATCH 13/50] Add `setuptools` to dependencies (#918) --- poetry.lock | 13 ++++++++++++- pyproject.toml | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index b0fc3cf8..32f45d8d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1496,6 +1496,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2403,6 +2413,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3495,4 +3506,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "beeecfa098d80f15b4ab1fec20916e4f3972a1d5afbf7f0c13c6590926273a94" +content-hash = "e23122b9db6581d69aa9205d7cb1d841d2236b578b89671ab7a0ac8946ce57e0" diff --git a/pyproject.toml b/pyproject.toml index 0b36460d..bc5dd92a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ python = ">=3.8,<4.0" "ruamel.yaml" = ">=0.17" # importlib.metadata has an API change in 3.10 and is no longer provisional importlib-metadata = { version = "^4", python = "<3.10" } +setuptools = ">=42.0.0" [tool.poetry.group.dev.dependencies] decorator = "*" From 7cac01b6038e05ef112b0423ba4aa8e31fcd913e Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Thu, 27 Jun 2024 11:49:03 +0200 Subject: [PATCH 14/50] Replace black & isort with ruff for formatting (#930) --- .github/workflows/main.yaml | 2 - CONTRIBUTING.rst | 10 +-- Makefile | 7 +- README.md | 2 +- docs/conf.py | 4 +- nornir/core/__init__.py | 8 +- nornir/core/configuration.py | 22 ++--- nornir/core/filter.py | 12 +-- nornir/core/helpers/jinja_helper.py | 9 +- nornir/core/inventory.py | 32 ++----- nornir/core/plugins/runners.py | 4 +- nornir/core/processor.py | 16 +--- nornir/core/state.py | 4 +- nornir/core/task.py | 12 ++- nornir/plugins/inventory/simple.py | 4 +- poetry.lock | 101 +--------------------- pyproject.toml | 10 ++- tests/conftest.py | 8 +- tests/core/test_InitNornir.py | 18 +--- tests/core/test_configuration.py | 8 +- tests/core/test_connections.py | 18 +--- tests/core/test_inventory.py | 38 ++------ tests/core/test_processors.py | 8 +- tests/core/test_tasks.py | 8 +- tests/plugins/processors/test_threaded.py | 4 +- 25 files changed, 77 insertions(+), 292 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 2c899adc..998ee30f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -38,8 +38,6 @@ jobs: - name: Run ruff run: make ruff - - name: Run black - run: make black - name: Run mypy run: make mypy - name: Run sphinx diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 61a4ce16..26fa12bf 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -81,7 +81,7 @@ The guidelines to pin dependencies are: a. if semver is supported we pin to major release b. if semver is not supported we pin to specific version 2. For development: - a. black is pinned to a specific version + a. ruff is pinned to a specific version b. everything is set to * Then, to update them: @@ -109,17 +109,17 @@ You can then stop them with: Coding style ------------ -Nornir uses `Black `_, the uncompromising Python code formatter. Black makes it easy for you to format your code as you can do so automatically after installing it. +Nornir uses `Ruff `_. Ruff makes it easy for you to format your code as you can do so automatically after installing it. .. code-block:: bash - poetry run black . + poetry run ruff format --check . -The Black GitHub repo has information about how you can integrate Black in your editor. +The Ruff GitHub repo has information about how you can integrate Ruff in your editor. Tests ------------- -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``. +As part of the automatic CI on every pull request, besides coding style checks and 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): diff --git a/Makefile b/Makefile index f0b13e34..e28e4498 100644 --- a/Makefile +++ b/Makefile @@ -14,11 +14,6 @@ docker: pytest: poetry run pytest --cov=nornir --cov-report=term-missing -vs ${ARGS} -.PHONY: black -black: - poetry run black --check ${NORNIR_DIRS} - poetry run isort --profile black --check ${NORNIR_DIRS} - .PHONY: sphinx sphinx: # TODO REPLACE with: sphinx-build -n -E -q -N -b dummy -d docs/_build/doctrees docs asd @@ -40,7 +35,7 @@ ruff: poetry run ruff check . .PHONY: tests -tests: ruff black mypy nbval pytest sphinx +tests: ruff mypy nbval pytest sphinx .PHONY: docker-tests docker-tests: docker diff --git a/README.md b/README.md index eb030f4b..9ce533ad 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build Status](https://github.com/nornir-automation/nornir/workflows/test%20nornir/badge.svg) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) [![Coverage Status](https://coveralls.io/repos/github/nornir-automation/nornir/badge.svg?branch=develop)](https://coveralls.io/github/nornir-automation/nornir?branch=develop) +![Build Status](https://github.com/nornir-automation/nornir/workflows/test%20nornir/badge.svg) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Coverage Status](https://coveralls.io/repos/github/nornir-automation/nornir/badge.svg?branch=develop)](https://coveralls.io/github/nornir-automation/nornir?branch=develop) Nornir diff --git a/docs/conf.py b/docs/conf.py index b788d0d6..fb8263d4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -142,9 +142,7 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, "nornir.tex", "nornir Documentation", "David Barroso", "manual") -] +latex_documents = [(master_doc, "nornir.tex", "nornir Documentation", "David Barroso", "manual")] # -- Options for manual page output --------------------------------------- diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index b30f17b7..449f40ac 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -62,9 +62,7 @@ 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 original object is left unmodified. """ - return Nornir( - **{**self._clone_parameters(), **{"processors": Processors(processors)}} - ) + return Nornir(**{**self._clone_parameters(), **{"processors": Processors(processors)}}) def with_runner(self, runner: RunnerPlugin) -> "Nornir": """ @@ -145,9 +143,7 @@ def run( result = self.runner.run(run_task, run_on) raise_on_error = ( - raise_on_error - if raise_on_error is not None - else self.config.core.raise_on_error + raise_on_error if raise_on_error is not None else self.config.core.raise_on_error ) # noqa if raise_on_error: result.raise_on_error() diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 8a04c02f..85f4e46b 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -58,9 +58,7 @@ class SSHConfig(object): __slots__ = ("config_file",) class Parameters: - config_file = Parameter( - default=DEFAULT_SSH_CONFIG, envvar="NORNIR_SSH_CONFIG_FILE" - ) + config_file = Parameter(default=DEFAULT_SSH_CONFIG, envvar="NORNIR_SSH_CONFIG_FILE") def __init__(self, config_file: Optional[str] = None) -> None: self.config_file = self.Parameters.config_file.resolve(config_file) @@ -73,13 +71,9 @@ class InventoryConfig(object): __slots__ = "plugin", "options", "transform_function", "transform_function_options" class Parameters: - plugin = Parameter( - typ=str, default="SimpleInventory", envvar="NORNIR_INVENTORY_PLUGIN" - ) + plugin = Parameter(typ=str, default="SimpleInventory", envvar="NORNIR_INVENTORY_PLUGIN") options = Parameter(default={}, envvar="NORNIR_INVENTORY_OPTIONS") - transform_function = Parameter( - typ=str, envvar="NORNIR_INVENTORY_TRANSFORM_FUNCTION" - ) + transform_function = Parameter(typ=str, envvar="NORNIR_INVENTORY_TRANSFORM_FUNCTION") transform_function_options = Parameter( default={}, envvar="NORNIR_INVENTORY_TRANSFORM_FUNCTION_OPTIONS" ) @@ -93,13 +87,9 @@ def __init__( ) -> None: self.plugin = self.Parameters.plugin.resolve(plugin) self.options = self.Parameters.options.resolve(options) or {} - self.transform_function = self.Parameters.transform_function.resolve( - transform_function - ) - self.transform_function_options = ( - self.Parameters.transform_function_options.resolve( - transform_function_options - ) + self.transform_function = self.Parameters.transform_function.resolve(transform_function) + self.transform_function_options = self.Parameters.transform_function_options.resolve( + transform_function_options ) def dict(self) -> Dict[str, Any]: diff --git a/nornir/core/filter.py b/nornir/core/filter.py index c6507fa6..91665f0b 100644 --- a/nornir/core/filter.py +++ b/nornir/core/filter.py @@ -47,9 +47,7 @@ def __init__(self, **kwargs: Any) -> None: self.filters = kwargs def __call__(self, host: Host) -> bool: - return all( - F._verify_rules(host, k.split("__"), v) for k, v in self.filters.items() - ) + return all(F._verify_rules(host, k.split("__"), v) for k, v in self.filters.items()) def __and__(self, other: "F") -> AND: return AND(self, other) @@ -106,16 +104,12 @@ def _verify_rules(data: Any, rule: List[str], value: Any) -> bool: return bool(data.get(rule[0]) == value) else: - raise Exception( - "I don't know how I got here:\n{}\n{}\n{}".format(data, rule, value) - ) + raise Exception("I don't know how I got here:\n{}\n{}\n{}".format(data, rule, value)) class NOT_F(F): def __call__(self, host: Host) -> bool: - return not any( - F._verify_rules(host, k.split("__"), v) for k, v in self.filters.items() - ) + return not any(F._verify_rules(host, k.split("__"), v) for k, v in self.filters.items()) def __invert__(self) -> F: return F(**self.filters) diff --git a/nornir/core/helpers/jinja_helper.py b/nornir/core/helpers/jinja_helper.py index 3b3466d3..f2d8ad64 100644 --- a/nornir/core/helpers/jinja_helper.py +++ b/nornir/core/helpers/jinja_helper.py @@ -4,15 +4,10 @@ def render_from_file( - path: str, - template: str, - jinja_filters: Optional[Dict[str, Any]] = None, - **kwargs: Any + path: str, template: str, jinja_filters: Optional[Dict[str, Any]] = None, **kwargs: Any ) -> str: jinja_filters = jinja_filters or {} - env = Environment( - loader=FileSystemLoader(path), undefined=StrictUndefined, trim_blocks=True - ) + env = Environment(loader=FileSystemLoader(path), undefined=StrictUndefined, trim_blocks=True) env.filters.update(jinja_filters) t = env.get_template(template) return t.render(**kwargs) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index f900dbff..524e7b35 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -150,9 +150,7 @@ def dict(self) -> Dict[str, Any]: return { "groups": [g.name for g in self.groups], "data": self.data, - "connection_options": { - k: v.dict() for k, v in self.connection_options.items() - }, + "connection_options": {k: v.dict() for k, v in self.connection_options.items()}, **super().dict(), } @@ -230,9 +228,7 @@ def schema(self) -> Dict[str, Any]: def dict(self) -> Dict[str, Any]: return { "data": self.data, - "connection_options": { - k: v.dict() for k, v in self.connection_options.items() - }, + "connection_options": {k: v.dict() for k, v in self.connection_options.items()}, **super().dict(), } @@ -298,9 +294,7 @@ def schema(cls) -> Dict[str, Any]: def dict(self) -> Dict[str, Any]: return { "name": self.name, - "connection_options": { - k: v.dict() for k, v in self.connection_options.items() - }, + "connection_options": {k: v.dict() for k, v in self.connection_options.items()}, **super().dict(), } @@ -405,9 +399,7 @@ def get(self, item: str, default: Any = None) -> Any: except KeyError: return default - def get_connection_parameters( - self, connection: Optional[str] = None - ) -> ConnectionOptions: + def get_connection_parameters(self, connection: Optional[str] = None) -> ConnectionOptions: if not connection: d = ConnectionOptions( hostname=self.hostname, @@ -439,9 +431,7 @@ def get_connection_parameters( ) return d - def _get_connection_options_recursively( - self, connection: str - ) -> Optional[ConnectionOptions]: + def _get_connection_options_recursively(self, connection: str) -> Optional[ConnectionOptions]: p = self.connection_options.get(connection) if p is None: p = ConnectionOptions(None, None, None, None, None, None) @@ -579,13 +569,11 @@ class Groups(Dict[str, Group]): class TransformFunction(Protocol): - def __call__(self, host: Host, **kwargs: Any) -> None: - ... + def __call__(self, host: Host, **kwargs: Any) -> None: ... class FilterObj(Protocol): - def __call__(self, host: Host, **kwargs: Any) -> bool: - ... + def __call__(self, host: Host, **kwargs: Any) -> bool: ... class Inventory(object): @@ -607,13 +595,11 @@ def filter( self, filter_obj: Optional[FilterObj] = None, filter_func: Optional[FilterObj] = None, - **kwargs: Any + **kwargs: Any, ) -> "Inventory": filter_func = filter_obj or filter_func if filter_func: - filtered = Hosts( - {n: h for n, h in self.hosts.items() if filter_func(h, **kwargs)} - ) + filtered = Hosts({n: h for n, h in self.hosts.items() if filter_func(h, **kwargs)}) else: filtered = Hosts( { diff --git a/nornir/core/plugins/runners.py b/nornir/core/plugins/runners.py index 1f9dca07..1537a826 100644 --- a/nornir/core/plugins/runners.py +++ b/nornir/core/plugins/runners.py @@ -21,6 +21,4 @@ def run(self, task: Task, hosts: List[Host]) -> AggregatedResult: raise NotImplementedError("needs to be implemented by the plugin") -RunnersPluginRegister: PluginRegister[Type[RunnerPlugin]] = PluginRegister( - RUNNERS_PLUGIN_PATH -) +RunnersPluginRegister: PluginRegister[Type[RunnerPlugin]] = PluginRegister(RUNNERS_PLUGIN_PATH) diff --git a/nornir/core/processor.py b/nornir/core/processor.py index 98bba7a1..5b6f4308 100644 --- a/nornir/core/processor.py +++ b/nornir/core/processor.py @@ -30,9 +30,7 @@ def task_instance_started(self, task: Task, host: Host) -> None: """ raise NotImplementedError("needs to be implemented by the processor") - def task_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def task_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: """ This method is called when a host completes its instance of a task """ @@ -44,9 +42,7 @@ def subtask_instance_started(self, task: Task, host: Host) -> None: """ raise NotImplementedError("needs to be implemented by the processor") - def subtask_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def subtask_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: """ This method is called when a host completes executing a subtask """ @@ -76,9 +72,7 @@ def task_instance_started(self, task: Task, host: Host) -> None: for p in self: p.task_instance_started(task, host) - def task_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def task_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: for p in self: p.task_instance_completed(task, host, result) @@ -86,8 +80,6 @@ def subtask_instance_started(self, task: Task, host: Host) -> None: for p in self: p.subtask_instance_started(task, host) - def subtask_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def subtask_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: for p in self: p.subtask_instance_completed(task, host, result) diff --git a/nornir/core/state.py b/nornir/core/state.py index 3c58f36b..4e00e6d8 100644 --- a/nornir/core/state.py +++ b/nornir/core/state.py @@ -12,9 +12,7 @@ class GlobalState(object): __slots__ = "dry_run", "failed_hosts" - def __init__( - self, dry_run: bool = False, failed_hosts: Optional[Set[str]] = None - ) -> None: + def __init__(self, dry_run: bool = False, failed_hosts: Optional[Set[str]] = None) -> None: self.dry_run = dry_run self.failed_hosts = failed_hosts or set() diff --git a/nornir/core/task.py b/nornir/core/task.py index 979fe5de..2000881d 100644 --- a/nornir/core/task.py +++ b/nornir/core/task.py @@ -47,7 +47,7 @@ def __init__( name: Optional[str] = None, severity_level: int = DEFAULT_SEVERITY_LEVEL, parent_task: Optional["Task"] = None, - **kwargs: str + **kwargs: str, ): self.task = task self.nornir = nornir @@ -68,7 +68,7 @@ def copy(self) -> "Task": self.name, self.severity_level, self.parent_task, - **self.params + **self.params, ) def __repr__(self) -> str: @@ -163,7 +163,7 @@ def grouped_tasks(task): global_dry_run=self.global_dry_run, processors=self.processors, parent_task=self, - **kwargs + **kwargs, ) r = run_task.start(self.host) self.results.append(r[0] if len(r) == 1 else cast("Result", r)) @@ -213,7 +213,7 @@ def __init__( failed: bool = False, exception: Optional[BaseException] = None, severity_level: int = DEFAULT_SEVERITY_LEVEL, - **kwargs: Any + **kwargs: Any, ): self.result = result self.host = host @@ -286,9 +286,7 @@ def __init__(self, name: str, **kwargs: MultiResult): super().__init__(**kwargs) def __repr__(self) -> str: - return "{} ({}): {}".format( - self.__class__.__name__, self.name, super().__repr__() - ) + return "{} ({}): {}".format(self.__class__.__name__, self.name, super().__repr__()) @property def failed(self) -> bool: diff --git a/nornir/plugins/inventory/simple.py b/nornir/plugins/inventory/simple.py index 0ee0884c..107537a7 100644 --- a/nornir/plugins/inventory/simple.py +++ b/nornir/plugins/inventory/simple.py @@ -56,9 +56,7 @@ def _get_inventory_element( password=data.get("password"), platform=data.get("platform"), data=data.get("data"), - groups=data.get( - "groups" - ), # this is a hack, we will convert it later to the correct type + groups=data.get("groups"), # this is a hack, we will convert it later to the correct type defaults=defaults, connection_options=_get_connection_options(data.get("connection_options", {})), ) diff --git a/poetry.lock b/poetry.lock index 32f45d8d..430da27b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -245,52 +245,6 @@ soupsieve = ">1.2" html5lib = ["html5lib"] lxml = ["lxml"] -[[package]] -name = "black" -version = "23.9.1" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, - {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, - {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, - {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, - {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, - {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, - {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, - {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, - {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, - {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, - {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "bleach" version = "6.0.0" @@ -483,20 +437,6 @@ files = [ {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -950,23 +890,6 @@ files = [ [package.dependencies] arrow = ">=0.15.0" -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - [[package]] name = "jedi" version = "0.19.1" @@ -1496,16 +1419,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2009,17 +1922,6 @@ files = [ qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] testing = ["docopt", "pytest (<6.0.0)"] -[[package]] -name = "pathspec" -version = "0.11.2" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, -] - [[package]] name = "pexpect" version = "4.8.0" @@ -2413,7 +2315,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3506,4 +3407,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "e23122b9db6581d69aa9205d7cb1d841d2236b578b89671ab7a0ac8946ce57e0" +content-hash = "37134dc424f8169de36942d71513d6914ab0866c5fedaebc0c3a074a0279b697" diff --git a/pyproject.toml b/pyproject.toml index bc5dd92a..52b3cdb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,8 +38,6 @@ nbval = "^0.10.0" pytest = "*" pytest-cov = "*" requests-mock = "*" -black = "^23.9.1" -isort = "^5.12.0" mypy = "^1.5.1" types-Jinja2 = "^2.11.9" types-pkg-resources = "^0.1.3" @@ -122,8 +120,10 @@ select = [ ] ignore = [ + "ISC001", # Recommended to be disabled when used with ruff formatter "N801", # Class name should use CapWords convention "N818", # Exception name should be named with an Error suffix + ################################################################################################## # The ignored rules below should be removed once the code has been updated, they are included # # like this so that we can reactivate them one by one. Alternatively ignored after further # @@ -180,6 +180,12 @@ ignore = [ "UP037", # Remove quotes from type annotation ] +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" + [tool.ruff.lint.mccabe] max-complexity = 12 diff --git a/tests/conftest.py b/tests/conftest.py index feab13c4..3cd2b7b1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -70,9 +70,7 @@ def get_inventory_element(typ, data, name, defaults): "groups" ), # this is a hack, we will convert it later to the correct type defaults=defaults, - connection_options=get_connection_options( - data.get("connection_options", {}) - ), + connection_options=get_connection_options(data.get("connection_options", {})), ) host_file = f"{dir_path}/inventory_data/hosts.yaml" @@ -126,9 +124,7 @@ def inv(request): @pytest.fixture(scope="session", autouse=True) def nornir(request): """Initializes nornir""" - nr = Nornir( - inventory=inventory_from_yaml(), runner=SerialRunner(), data=global_data - ) + nr = Nornir(inventory=inventory_from_yaml(), runner=SerialRunner(), data=global_data) return nr diff --git a/tests/core/test_InitNornir.py b/tests/core/test_InitNornir.py index c926b634..3c0ba330 100644 --- a/tests/core/test_InitNornir.py +++ b/tests/core/test_InitNornir.py @@ -18,9 +18,7 @@ "version": 1, "disable_existing_loggers": True, "formatters": { - "standard": { - "format": "[%(asctime)s] %(levelname)-8s {%(name)s:%(lineno)d} %(message)s" - } + "standard": {"format": "[%(asctime)s] %(levelname)-8s {%(name)s:%(lineno)d} %(message)s"} }, "handlers": { "console": { @@ -60,9 +58,7 @@ def load(self): InventoryPluginRegister.register("inventory-test", InventoryTest) TransformFunctionRegister.register("transform_func", transform_func) -TransformFunctionRegister.register( - "transform_func_with_options", transform_func_with_options -) +TransformFunctionRegister.register("transform_func_with_options", transform_func_with_options) class Test(object): @@ -211,14 +207,8 @@ def test_InitNornir_logging_to_console(self): assert nornir_logger.level == logging.INFO assert len(nornir_logger.handlers) == 3 - assert any( - isinstance(handler, logging.FileHandler) - for handler in nornir_logger.handlers - ) - assert any( - isinstance(handler, logging.StreamHandler) - for handler in nornir_logger.handlers - ) + assert any(isinstance(handler, logging.FileHandler) for handler in nornir_logger.handlers) + assert any(isinstance(handler, logging.StreamHandler) for handler in nornir_logger.handlers) def test_InitNornir_logging_disabled(self): self.cleanup() diff --git a/tests/core/test_configuration.py b/tests/core/test_configuration.py index 9726a912..6d3b07a8 100644 --- a/tests/core/test_configuration.py +++ b/tests/core/test_configuration.py @@ -3,14 +3,10 @@ from nornir.core.configuration import Config -dir_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), "test_configuration" -) +dir_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_configuration") -DEFAULT_LOG_FORMAT = ( - "%(asctime)s - %(name)12s - %(levelname)8s - %(funcName)10s() - %(message)s" -) +DEFAULT_LOG_FORMAT = "%(asctime)s - %(name)12s - %(levelname)8s - %(funcName)10s() - %(message)s" class Test(object): diff --git a/tests/core/test_connections.py b/tests/core/test_connections.py index b18eb2ac..529b4369 100644 --- a/tests/core/test_connections.py +++ b/tests/core/test_connections.py @@ -57,9 +57,7 @@ def open( extras: Optional[Dict[str, Any]] = None, configuration: Optional[Config] = None, ) -> None: - raise FailedConnection( - f"Failed to open connection to {self.hostname}:{self.port}" - ) + raise FailedConnection(f"Failed to open connection to {self.hostname}:{self.port}") def close(self) -> None: pass @@ -113,9 +111,7 @@ def setup_class(cls): ConnectionPluginRegister.register("dummy", DummyConnectionPlugin) ConnectionPluginRegister.register("dummy2", DummyConnectionPlugin) ConnectionPluginRegister.register("dummy_no_overrides", DummyConnectionPlugin) - ConnectionPluginRegister.register( - FailedConnectionPlugin.name, FailedConnectionPlugin - ) + ConnectionPluginRegister.register(FailedConnectionPlugin.name, FailedConnectionPlugin) def test_open_and_close_connection(self, nornir): nr = nornir.filter(name="dev2.group_1") @@ -138,10 +134,7 @@ def test_close_not_opened_connection(self, nornir): def test_failed_connection(self, nornir): nr = nornir.filter(name="dev2.group_1") nr.run(task=failed_connection, nornir_config=nornir.config) - assert ( - FailedConnectionPlugin.name - not in nornir.inventory.hosts["dev2.group_1"].connections - ) + assert FailedConnectionPlugin.name not in nornir.inventory.hosts["dev2.group_1"].connections def test_context_manager(self, nornir): with nornir.filter(name="dev2.group_1") as nr: @@ -247,10 +240,7 @@ def test_deregister_all(self): def test_get_plugin(self): assert ConnectionPluginRegister.get_plugin("dummy") == DummyConnectionPlugin - assert ( - ConnectionPluginRegister.get_plugin("another_dummy") - == AnotherDummyConnectionPlugin - ) + assert ConnectionPluginRegister.get_plugin("another_dummy") == AnotherDummyConnectionPlugin assert len(ConnectionPluginRegister.available) == 2 def test_nonexistent_plugin(self): diff --git a/tests/core/test_inventory.py b/tests/core/test_inventory.py index 1d84cce4..995a865d 100644 --- a/tests/core/test_inventory.py +++ b/tests/core/test_inventory.py @@ -388,9 +388,7 @@ def test_filtering(self, inv): www_site1 = sorted(list(inv.filter(role="www", site="site1").hosts.keys())) assert www_site1 == ["dev1.group_1"] - www_site1 = sorted( - list(inv.filter(role="www").filter(site="site1").hosts.keys()) - ) + www_site1 = sorted(list(inv.filter(role="www").filter(site="site1").hosts.keys())) assert www_site1 == ["dev1.group_1"] def test_filtering_func(self, inv): @@ -402,9 +400,7 @@ def test_filtering_func(self, inv): def longer_than(dev, length): return len(dev["my_var"]) > length - long_names = sorted( - list(inv.filter(filter_func=longer_than, length=20).hosts.keys()) - ) + long_names = sorted(list(inv.filter(filter_func=longer_than, length=20).hosts.keys())) assert long_names == ["dev1.group_1", "dev4.group_2", "dev6.group_3"] def test_filter_unique_keys(self, inv): @@ -527,9 +523,7 @@ def test_add_host(self): hosts = {"h1": h1, "h2": h2} groups = {"g1": g1, "g2": g2} inv = inventory.Inventory(hosts=hosts, groups=groups, defaults=defaults) - h3_connection_options = inventory.ConnectionOptions( - extras={"device_type": "cisco_ios"} - ) + h3_connection_options = inventory.ConnectionOptions(extras={"device_type": "cisco_ios"}) inv.hosts["h3"] = inventory.Host( name="h3", groups=[g1], @@ -542,10 +536,7 @@ def test_add_host(self): assert "test_var" in inv.hosts["h3"].defaults.data.keys() assert inv.hosts["h3"].defaults.data.get("test_var") == "test_value" assert inv.hosts["h3"].platform == "TestPlatform" - assert ( - inv.hosts["h3"].connection_options["netmiko"].extras["device_type"] - == "cisco_ios" - ) + assert inv.hosts["h3"].connection_options["netmiko"].extras["device_type"] == "cisco_ios" def test_add_group(self): connection_options = {"username": "test_user", "password": "test_pass"} @@ -558,9 +549,7 @@ def test_add_group(self): hosts = {"h1": h1, "h2": h2} groups = {"g1": g1, "g2": g2} inv = inventory.Inventory(hosts=hosts, groups=groups, defaults=defaults) - g3_connection_options = inventory.ConnectionOptions( - extras={"device_type": "cisco_ios"} - ) + g3_connection_options = inventory.ConnectionOptions(extras={"device_type": "cisco_ios"}) inv.groups["g3"] = inventory.Group( name="g3", username="test_user", @@ -569,18 +558,11 @@ def test_add_group(self): ) assert "g1" in [i.name for i in inv.groups["g2"].groups] assert "g3" in inv.groups - assert ( - inv.groups["g3"].defaults.connection_options.get("username") == "test_user" - ) - assert ( - inv.groups["g3"].defaults.connection_options.get("password") == "test_pass" - ) + assert inv.groups["g3"].defaults.connection_options.get("username") == "test_user" + assert inv.groups["g3"].defaults.connection_options.get("password") == "test_pass" assert "test_var" in inv.groups["g3"].defaults.data.keys() assert "test_value" == inv.groups["g3"].defaults.data.get("test_var") - assert ( - inv.groups["g3"].connection_options["netmiko"].extras["device_type"] - == "cisco_ios" - ) + assert inv.groups["g3"].connection_options["netmiko"].extras["device_type"] == "cisco_ios" def test_dict(self, inv): inventory_dict = inv.dict() @@ -610,9 +592,7 @@ def test_get_groups_dict(self, inv): def test_get_hosts_dict(self, inv): hosts_dict = {n: h.dict() for n, h in inv.hosts.items()} dev1_groups = hosts_dict["dev1.group_1"]["groups"] - dev2_paramiko_opts = hosts_dict["dev2.group_1"]["connection_options"][ - "paramiko" - ] + dev2_paramiko_opts = hosts_dict["dev2.group_1"]["connection_options"]["paramiko"] assert isinstance(hosts_dict, dict) assert "group_1" in dev1_groups assert dev2_paramiko_opts["username"] == "root" diff --git a/tests/core/test_processors.py b/tests/core/test_processors.py index 5bede97d..eb27b663 100644 --- a/tests/core/test_processors.py +++ b/tests/core/test_processors.py @@ -35,9 +35,7 @@ def task_completed(self, task: Task, result: AggregatedResult) -> None: def task_instance_started(self, task: Task, host: Host) -> None: self.data[task.name][host.name] = {"started": True, "subtasks": {}} - def task_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def task_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: self.data[task.name][host.name]["completed"] = True self.data[task.name][host.name]["failed"] = result.failed @@ -59,9 +57,7 @@ def subtask_instance_started(self, task: Task, host: Host) -> None: data = self._get_subtask_dict(task, host) data[task.name] = {"started": True, "subtasks": {}} - def subtask_instance_completed( - self, task: Task, host: Host, result: MultiResult - ) -> None: + def subtask_instance_completed(self, task: Task, host: Host, result: MultiResult) -> None: data = self._get_subtask_dict(task, host) data[task.name]["completed"] = True data[task.name]["failed"] = result.failed diff --git a/tests/core/test_tasks.py b/tests/core/test_tasks.py index cbd61f69..3573a165 100644 --- a/tests/core/test_tasks.py +++ b/tests/core/test_tasks.py @@ -96,9 +96,7 @@ def test_run_on(self, nornir): assert "dev3.group_2" in result assert "dev1.group_1" in result - result = nornir.run( - a_task_for_testing, fail_on=["dev3.group_2"], on_failed=True - ) + result = nornir.run(a_task_for_testing, fail_on=["dev3.group_2"], on_failed=True) assert result.failed assert "dev3.group_2" in result assert "dev1.group_1" in result @@ -166,9 +164,7 @@ def test_dry_run(self, nornir): r = host.run(a_task_to_test_dry_run, expected_dry_run_value=True) assert not r["dev3.group_2"].failed - r = host.run( - a_task_to_test_dry_run, dry_run=False, expected_dry_run_value=False - ) + r = host.run(a_task_to_test_dry_run, dry_run=False, expected_dry_run_value=False) assert not r["dev3.group_2"].failed nornir.data.dry_run = False diff --git a/tests/plugins/processors/test_threaded.py b/tests/plugins/processors/test_threaded.py index 38c18498..2a0dfb08 100644 --- a/tests/plugins/processors/test_threaded.py +++ b/tests/plugins/processors/test_threaded.py @@ -41,9 +41,7 @@ def verify_data_change(task): class Test(object): def test_blocking_task_multithreading(self, nornir): t1 = datetime.datetime.now() - nornir.with_runner(ThreadedRunner(num_workers=NUM_WORKERS)).run( - blocking_task, wait=2 - ) + nornir.with_runner(ThreadedRunner(num_workers=NUM_WORKERS)).run(blocking_task, wait=2) t2 = datetime.datetime.now() delta = t2 - t1 assert delta.seconds == 2, delta From 7a93f23361c558b36b9d10c92bbbf30c3686e76e Mon Sep 17 00:00:00 2001 From: Urs Baumann Date: Fri, 28 Jun 2024 00:42:12 +0200 Subject: [PATCH 15/50] Fix Sphinx add custom css issue (#933) --- .github/workflows/main.yaml | 2 +- Makefile | 10 ++-------- docs/conf.py | 9 ++------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 998ee30f..70f2721f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,7 +43,7 @@ jobs: - name: Run sphinx run: | sudo apt-get install pandoc - make sphinx + make docs pytest: name: Testing on Python ${{ matrix.python-version }} (${{ matrix.platform}}) diff --git a/Makefile b/Makefile index e28e4498..0c8f5c62 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,6 @@ docker: pytest: poetry run pytest --cov=nornir --cov-report=term-missing -vs ${ARGS} -.PHONY: sphinx -sphinx: - # TODO REPLACE with: sphinx-build -n -E -q -N -b dummy -d docs/_build/doctrees docs asd - # poetry run sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html - echo "WARNING: sphinx needs to be added here!!!" - .PHONY: mypy mypy: poetry run mypy nornir tests @@ -43,5 +37,5 @@ docker-tests: docker .PHONY: docs docs: - ./docs/build_api.sh - make -C docs clean html + poetry run ./docs/build_api.sh + poetry run make -C docs clean html diff --git a/docs/conf.py b/docs/conf.py index fb8263d4..47b1b225 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,8 +21,6 @@ import sys from typing import Dict -from sphinx.application import Sphinx - from nornir import __version__ sys.path.insert(0, os.path.abspath("../")) @@ -70,7 +68,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -171,7 +169,4 @@ issues_github_path = "nornir-automation/nornir" - -def setup(app: Sphinx) -> None: - """Map methods to states of the documentation build.""" - app.add_stylesheet("css/custom.css") +html_css_files = ["css/custom.css"] From 7ab248ccb09e30a0764cb4eff17b5313c445b88c Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 28 Jun 2024 09:25:08 +0200 Subject: [PATCH 16/50] Sort slots - Fix RUF023 (#936) --- nornir/core/configuration.py | 10 +++++----- nornir/core/inventory.py | 10 +++++----- pyproject.toml | 1 - 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 85f4e46b..43a5e844 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -68,7 +68,7 @@ def dict(self) -> Dict[str, Any]: class InventoryConfig(object): - __slots__ = "plugin", "options", "transform_function", "transform_function_options" + __slots__ = "options", "plugin", "transform_function", "transform_function_options" class Parameters: plugin = Parameter(typ=str, default="SimpleInventory", envvar="NORNIR_INVENTORY_PLUGIN") @@ -102,7 +102,7 @@ def dict(self) -> Dict[str, Any]: class LoggingConfig(object): - __slots__ = "enabled", "level", "log_file", "format", "to_console", "loggers" + __slots__ = "enabled", "format", "level", "log_file", "loggers", "to_console" class Parameters: enabled = Parameter(default=True, envvar="NORNIR_LOGGING_ENABLED") @@ -195,7 +195,7 @@ def configure(self) -> None: class RunnerConfig(object): - __slots__ = ("plugin", "options") + __slots__ = ("options", "plugin") class Parameters: plugin = Parameter(default="threaded", envvar="NORNIR_RUNNER_PLUGIN") @@ -232,10 +232,10 @@ def dict(self) -> Dict[str, Any]: class Config(object): __slots__ = ( "core", - "runner", - "ssh", "inventory", "logging", + "runner", + "ssh", "user_defined", ) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index 524e7b35..d4e1077c 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -21,7 +21,7 @@ class BaseAttributes(object): - __slots__ = ("hostname", "port", "username", "password", "platform") + __slots__ = ("hostname", "password", "platform", "port", "username") def __init__( self, @@ -113,7 +113,7 @@ def add(self, group: "Group") -> None: class InventoryElement(BaseAttributes): - __slots__ = ("groups", "data", "connection_options") + __slots__ = ("connection_options", "data", "groups") def __init__( self, @@ -195,7 +195,7 @@ def extended_groups(self) -> List["Group"]: class Defaults(BaseAttributes): - __slots__ = ("data", "connection_options") + __slots__ = ("connection_options", "data") def __init__( self, @@ -234,7 +234,7 @@ def dict(self) -> Dict[str, Any]: class Host(InventoryElement): - __slots__ = ("name", "connections", "defaults") + __slots__ = ("connections", "defaults", "name") def __init__( self, @@ -577,7 +577,7 @@ def __call__(self, host: Host, **kwargs: Any) -> bool: ... class Inventory(object): - __slots__ = ("hosts", "groups", "defaults") + __slots__ = ("defaults", "groups", "hosts") def __init__( self, diff --git a/pyproject.toml b/pyproject.toml index 52b3cdb9..1f043f2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -161,7 +161,6 @@ ignore = [ "RSE102", # Unnecessary parentheses on raised exception "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "RUF023", # `__slots__` is not sorted "RUF100", # Unused blanket `noqa` directive "S701", # By default, jinja2 sets `autoescape` to `False`. Consider using `autoescape=True` or the `select_autoescape` function to mitigate XSS vulnerabilities. "SLF001", # Private member accessed From c132a3fcb3ea58202744ba924b226dea8ca96aac Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 28 Jun 2024 09:25:28 +0200 Subject: [PATCH 17/50] Remove unused import that no longer exists (#937) --- nornir/core/configuration.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 43a5e844..8b9a9ca7 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -5,16 +5,12 @@ import sys import warnings from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, TypeVar +from typing import Any, Dict, List, Optional, Type, TypeVar import ruamel.yaml from nornir.core.exceptions import ConflictingConfigurationWarning -if TYPE_CHECKING: - from nornir.core.deserializer.inventory import Inventory # noqa - - DEFAULT_SSH_CONFIG = str(Path("~/.ssh/config").expanduser()) T = TypeVar("T") From ecef440f8541181476ad969794be8e01513cf4fe Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 28 Jun 2024 09:25:49 +0200 Subject: [PATCH 18/50] Remove quotes from type-annotations (UP037) (#938) --- nornir/core/inventory.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index d4e1077c..ad318863 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -181,7 +181,7 @@ def extended_groups(self) -> List["Group"]: this will return [group_a, group_1, group_X, group_2, group_b, group_3] """ - groups: List["Group"] = [] + groups: List[Group] = [] for g in self.groups: if g not in groups: diff --git a/pyproject.toml b/pyproject.toml index 1f043f2e..0466e9cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -176,7 +176,7 @@ ignore = [ "UP015", # Unnecessary open mode parameters "UP032", # Use f-string instead of `format` call "UP034", # Avoid extraneous parentheses - "UP037", # Remove quotes from type annotation + #"UP037", # Remove quotes from type annotation ] [tool.ruff.format] From 90338cf8f17a4f5b9554a041956a5ff3878bf976 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 28 Jun 2024 09:26:11 +0200 Subject: [PATCH 19/50] Use cls as first classmethod argument (Fix: N804) (#939) --- nornir/core/inventory.py | 6 +++--- pyproject.toml | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index ad318863..a332b846 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -79,7 +79,7 @@ def __init__( ) @classmethod - def schema(self) -> Dict[str, Any]: + def schema(cls) -> Dict[str, Any]: return { "extras": {"$key": "$value"}, **super().schema(), @@ -138,7 +138,7 @@ def __init__( ) @classmethod - def schema(self) -> Dict[str, Any]: + def schema(cls) -> Dict[str, Any]: return { "groups": ["$group_name"], "data": {"$key": "$value"}, @@ -218,7 +218,7 @@ def __init__( ) @classmethod - def schema(self) -> Dict[str, Any]: + def schema(cls) -> Dict[str, Any]: return { "data": {"$key": "$value"}, "connection_options": {"$connection_type": ConnectionOptions.schema()}, diff --git a/pyproject.toml b/pyproject.toml index 0466e9cd..7183a77c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -141,7 +141,6 @@ ignore = [ "FBT002", # Boolean default positional argument in function definition "FURB101", # `open` and `read` should be replaced by `Path(filename).read_text()` "INP001", # File is part of an implicit namespace package. Add an `__init__.py`. - "N804", # First argument of a class method should be named `cls` "PERF203", # `try`-`except` within a loop incurs performance overhead "PGH004", # Use specific rule codes when using `noqa` "PIE800", # Unnecessary spread `**` From c9db6239147186f81e333eb4058632be7bc520dc Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 28 Jun 2024 10:03:36 +0200 Subject: [PATCH 20/50] Remove unnecessary `else` after `return` statement (Fix: RET505) (#940) --- nornir/core/filter.py | 27 +++++++++++++-------------- nornir/core/inventory.py | 11 +++++------ nornir/core/task.py | 3 +-- pyproject.toml | 1 - 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/nornir/core/filter.py b/nornir/core/filter.py index 91665f0b..a4300cde 100644 --- a/nornir/core/filter.py +++ b/nornir/core/filter.py @@ -80,28 +80,27 @@ def _verify_rules(data: Any, rule: List[str], value: Any) -> bool: if hasattr(data, operator): return getattr(data, operator)(value) is True - elif hasattr(data, rule[0]): + if hasattr(data, rule[0]): if callable(getattr(data, rule[0])): return bool(getattr(data, rule[0])(value)) + return bool(getattr(data, rule[0]) == value) - else: - return bool(getattr(data, rule[0]) == value) - - elif rule == ["in"]: + if rule == ["in"]: return bool(data in value) - elif rule == ["any"]: + + if rule == ["any"]: if isinstance(data, list): return any([x in data for x in value]) - else: - return any([x == data for x in value]) - elif rule == ["all"]: + return any([x == data for x in value]) + + if rule == ["all"]: if isinstance(data, list): return all([x in data for x in value]) - else: - # it doesn't make sense to check a single value meets more than one case - return False - else: - return bool(data.get(rule[0]) == value) + + # it doesn't make sense to check a single value meets more than one case + return False + + return bool(data.get(rule[0]) == value) else: raise Exception("I don't know how I got here:\n{}\n{}\n{}".format(data, rule, value)) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index a332b846..fcff2c76 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -96,8 +96,8 @@ class ParentGroups(List["Group"]): def __contains__(self, value: object) -> bool: if isinstance(value, str): return any([value == g.name for g in self]) - else: - return any([value == g for g in self]) + + return any([value == g for g in self]) def add(self, group: "Group") -> None: """ @@ -318,8 +318,7 @@ def has_parent_group(self, group: Union[str, "Group"]) -> bool: if isinstance(group, str): return self._has_parent_group_by_name(group) - else: - return self._has_parent_group_by_object(group) + return self._has_parent_group_by_object(group) def _has_parent_group_by_name(self, group: str) -> bool: for g in self.groups: @@ -362,8 +361,8 @@ def __getattribute__(self, name: str) -> Any: return r return object.__getattribute__(self.defaults, name) - else: - return v + + return v def __bool__(self) -> bool: return bool(self.name) diff --git a/nornir/core/task.py b/nornir/core/task.py index 2000881d..27e61fd6 100644 --- a/nornir/core/task.py +++ b/nornir/core/task.py @@ -237,8 +237,7 @@ def __str__(self) -> str: if self.exception: return str(self.exception) - else: - return str(self.result) + return str(self.result) class MultiResult(List[Result]): diff --git a/pyproject.toml b/pyproject.toml index 7183a77c..5ef74ddf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -155,7 +155,6 @@ ignore = [ "PTH120", # `os.path.dirname()` should be replaced by `Path.parent` "PTH123", # `open()` should be replaced by `Path.open()` "PYI036", # The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None` - "RET505", # Unnecessary `else` after `return` statement "RET504", # Unnecessary assignment before `return` statement "RSE102", # Unnecessary parentheses on raised exception "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? From 893a95dd12757288eb471289a51f27c1ba02b545 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 10:24:27 +0200 Subject: [PATCH 21/50] Bump tornado from 6.3.3 to 6.4.1 (#912) Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.3.3 to 6.4.1. - [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst) - [Commits](https://github.com/tornadoweb/tornado/compare/v6.3.3...v6.4.1) --- updated-dependencies: - dependency-name: tornado dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/poetry.lock b/poetry.lock index 430da27b..a6f65b2c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -1419,6 +1419,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2315,6 +2325,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3139,22 +3150,22 @@ files = [ [[package]] name = "tornado" -version = "6.3.3" +version = "6.4.1" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false -python-versions = ">= 3.8" -files = [ - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, - {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, - {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, - {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, +python-versions = ">=3.8" +files = [ + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, + {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, + {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, + {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, ] [[package]] From 0c86aeefba0f43148938833dab28334281e4e52c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 10:24:37 +0200 Subject: [PATCH 22/50] Bump requests from 2.31.0 to 2.32.2 (#915) Bumps [requests](https://github.com/psf/requests) from 2.31.0 to 2.32.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.31.0...v2.32.2) --- updated-dependencies: - dependency-name: requests dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index a6f65b2c..793eed00 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2525,13 +2525,13 @@ rpds-py = ">=0.7.0" [[package]] name = "requests" -version = "2.31.0" +version = "2.32.2" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, + {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, ] [package.dependencies] From 39d07eeb686856b5a1beb8323342e148555dbbca Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 28 Jun 2024 09:43:25 -0600 Subject: [PATCH 23/50] Update .readthedocs.yml (testing to see if it fixes RTD build issues) Will revert/change if it doesn't fix RTD issues. --- .readthedocs.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index c028a638..57501b92 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -2,17 +2,15 @@ version: 2 formats: [] build: - os: "ubuntu-22.04" + os: ubuntu-22.04 tools: python: "3.11" - jobs: - post_create_environment: - - pip install poetry - - poetry config virtualenvs.create false - post_install: - # Install dependencies with 'docs' dependency group - # https://python-poetry.org/docs/managing-dependencies/#dependency-groups - - poetry install --with docs + +python: + install: + - method: poetry + path: . + command: "poetry install --with docs" sphinx: configuration: docs/conf.py From 274a6d6579f71f43435ff25282306c950a7f4623 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 28 Jun 2024 10:39:59 -0600 Subject: [PATCH 24/50] Revert "Update .readthedocs.yml (testing to see if it fixes RTD build issues)" (#941) This reverts commit 39d07eeb686856b5a1beb8323342e148555dbbca. --- .readthedocs.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 57501b92..c028a638 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -2,15 +2,17 @@ version: 2 formats: [] build: - os: ubuntu-22.04 + os: "ubuntu-22.04" tools: python: "3.11" - -python: - install: - - method: poetry - path: . - command: "poetry install --with docs" + jobs: + post_create_environment: + - pip install poetry + - poetry config virtualenvs.create false + post_install: + # Install dependencies with 'docs' dependency group + # https://python-poetry.org/docs/managing-dependencies/#dependency-groups + - poetry install --with docs sphinx: configuration: docs/conf.py From 320b229f574fe4662accd9b5ed3a7427e33a782a Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 28 Jun 2024 14:30:29 -0600 Subject: [PATCH 25/50] Update RTD config to have poetry properly use RTD venv (#942) --- .readthedocs.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index c028a638..b4408131 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,11 +8,9 @@ build: jobs: post_create_environment: - pip install poetry - - poetry config virtualenvs.create false post_install: - # Install dependencies with 'docs' dependency group - # https://python-poetry.org/docs/managing-dependencies/#dependency-groups - - poetry install --with docs + # Instructs Poetry to use RTD venv + - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs sphinx: configuration: docs/conf.py From b1ddcda1243f1f34cdfd30b27c8d29b2a84f711f Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sun, 30 Jun 2024 19:10:20 +0200 Subject: [PATCH 26/50] Remove Python 2 style class definitions (#947) --- nornir/core/__init__.py | 2 +- nornir/core/configuration.py | 12 ++++++------ nornir/core/filter.py | 2 +- nornir/core/inventory.py | 4 ++-- nornir/core/state.py | 2 +- nornir/core/task.py | 4 ++-- pyproject.toml | 1 - tests/core/test_InitNornir.py | 2 +- tests/core/test_configuration.py | 2 +- tests/core/test_connections.py | 4 ++-- tests/core/test_filter.py | 2 +- tests/core/test_inventory.py | 2 +- tests/core/test_tasks.py | 2 +- tests/plugins/processors/test_serial.py | 2 +- tests/plugins/processors/test_threaded.py | 2 +- 15 files changed, 22 insertions(+), 23 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 449f40ac..4146f3d8 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -14,7 +14,7 @@ logger = logging.getLogger(__name__) -class Nornir(object): +class Nornir: """ This is the main object to work with. It contains the inventory and it serves as task dispatcher. diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 8b9a9ca7..357d9b30 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -50,7 +50,7 @@ def resolve(self, value: Optional[T]) -> T: return v -class SSHConfig(object): +class SSHConfig: __slots__ = ("config_file",) class Parameters: @@ -63,7 +63,7 @@ def dict(self) -> Dict[str, Any]: return {"config_file": self.config_file} -class InventoryConfig(object): +class InventoryConfig: __slots__ = "options", "plugin", "transform_function", "transform_function_options" class Parameters: @@ -97,7 +97,7 @@ def dict(self) -> Dict[str, Any]: } -class LoggingConfig(object): +class LoggingConfig: __slots__ = "enabled", "format", "level", "log_file", "loggers", "to_console" class Parameters: @@ -190,7 +190,7 @@ def configure(self) -> None: logger_.addHandler(stderr_handler) -class RunnerConfig(object): +class RunnerConfig: __slots__ = ("options", "plugin") class Parameters: @@ -210,7 +210,7 @@ def dict(self) -> Dict[str, Any]: } -class CoreConfig(object): +class CoreConfig: __slots__ = "raise_on_error" class Parameters: @@ -225,7 +225,7 @@ def dict(self) -> Dict[str, Any]: } -class Config(object): +class Config: __slots__ = ( "core", "inventory", diff --git a/nornir/core/filter.py b/nornir/core/filter.py index a4300cde..eb0db82a 100644 --- a/nornir/core/filter.py +++ b/nornir/core/filter.py @@ -3,7 +3,7 @@ from nornir.core.inventory import Host -class F_BASE(object): +class F_BASE: def __call__(self, host: Host) -> bool: raise NotImplementedError() diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index fcff2c76..f2615002 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -20,7 +20,7 @@ HostOrGroup = TypeVar("HostOrGroup", "Host", "Group") -class BaseAttributes(object): +class BaseAttributes: __slots__ = ("hostname", "password", "platform", "port", "username") def __init__( @@ -575,7 +575,7 @@ class FilterObj(Protocol): def __call__(self, host: Host, **kwargs: Any) -> bool: ... -class Inventory(object): +class Inventory: __slots__ = ("defaults", "groups", "hosts") def __init__( diff --git a/nornir/core/state.py b/nornir/core/state.py index 4e00e6d8..d04efee0 100644 --- a/nornir/core/state.py +++ b/nornir/core/state.py @@ -1,7 +1,7 @@ from typing import Any, Dict, Optional, Set -class GlobalState(object): +class GlobalState: """ This class is just a placeholder to share data amongst different versions of Nornir after running ``filter`` multiple times. diff --git a/nornir/core/task.py b/nornir/core/task.py index 27e61fd6..b7bb2f1d 100644 --- a/nornir/core/task.py +++ b/nornir/core/task.py @@ -14,7 +14,7 @@ DEFAULT_SEVERITY_LEVEL = logging.INFO -class Task(object): +class Task: """ A task is basically a wrapper around a function that has to be run against multiple devices. You won't probably have to deal with this class yourself as @@ -181,7 +181,7 @@ def is_dry_run(self, override: Optional[bool] = None) -> bool: return override if override is not None else self.global_dry_run -class Result(object): +class Result: """ Result of running individual tasks. diff --git a/pyproject.toml b/pyproject.toml index 5ef74ddf..64059753 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -169,7 +169,6 @@ ignore = [ "TRY004", # Prefer `TypeError` exception for invalid type "TRY300", # Consider moving this statement to an `else` block "TRY400", # Use `logging.exception` instead of `logging.error` - "UP004", # Class inherits from `object` "UP009", # UTF-8 encoding declaration is unnecessary "UP015", # Unnecessary open mode parameters "UP032", # Use f-string instead of `format` call diff --git a/tests/core/test_InitNornir.py b/tests/core/test_InitNornir.py index 3c0ba330..ba533b5a 100644 --- a/tests/core/test_InitNornir.py +++ b/tests/core/test_InitNornir.py @@ -61,7 +61,7 @@ def load(self): TransformFunctionRegister.register("transform_func_with_options", transform_func_with_options) -class Test(object): +class Test: def test_InitNornir_bare(self): os.chdir("tests/inventory_data/") nr = InitNornir() diff --git a/tests/core/test_configuration.py b/tests/core/test_configuration.py index 6d3b07a8..ce44de1e 100644 --- a/tests/core/test_configuration.py +++ b/tests/core/test_configuration.py @@ -9,7 +9,7 @@ DEFAULT_LOG_FORMAT = "%(asctime)s - %(name)12s - %(levelname)8s - %(funcName)10s() - %(message)s" -class Test(object): +class Test: def test_config_defaults(self): c = Config() assert c.dict() == { diff --git a/tests/core/test_connections.py b/tests/core/test_connections.py index 529b4369..1f773026 100644 --- a/tests/core/test_connections.py +++ b/tests/core/test_connections.py @@ -104,7 +104,7 @@ def validate_params(task, conn, params, nornir_config): assert getattr(task.host.connections[conn], k) == v -class Test(object): +class Test: @classmethod def setup_class(cls): ConnectionPluginRegister.deregister_all() @@ -200,7 +200,7 @@ def test_validate_params_overrides_groups(self, nornir): assert not r.failed -class TestConnectionPluginsRegistration(object): +class TestConnectionPluginsRegistration: def setup_method(self, method): ConnectionPluginRegister.deregister_all() ConnectionPluginRegister.register("dummy", DummyConnectionPlugin) diff --git a/tests/core/test_filter.py b/tests/core/test_filter.py index 276c56e4..74c27f93 100644 --- a/tests/core/test_filter.py +++ b/tests/core/test_filter.py @@ -3,7 +3,7 @@ from nornir.core.filter import AND, OR, F -class Test(object): +class Test: def test_simple(self, nornir): f = F(site="site1") filtered = sorted(list((nornir.inventory.filter(f).hosts.keys()))) diff --git a/tests/core/test_inventory.py b/tests/core/test_inventory.py index 995a865d..4f9563d1 100644 --- a/tests/core/test_inventory.py +++ b/tests/core/test_inventory.py @@ -16,7 +16,7 @@ inv_dict = {"hosts": hosts, "groups": groups, "defaults": defaults} -class Test(object): +class Test: def test_host(self): h = inventory.Host(name="host1", hostname="host1") assert h.hostname == "host1" diff --git a/tests/core/test_tasks.py b/tests/core/test_tasks.py index 3573a165..f78720a2 100644 --- a/tests/core/test_tasks.py +++ b/tests/core/test_tasks.py @@ -59,7 +59,7 @@ def fail_command_subtask_capture(task, fail_on=None): return "I captured this succcessfully" -class Test(object): +class Test: def test_task(self, nornir): result = nornir.run(a_task_for_testing) assert result diff --git a/tests/plugins/processors/test_serial.py b/tests/plugins/processors/test_serial.py index c21a9dae..47199d64 100644 --- a/tests/plugins/processors/test_serial.py +++ b/tests/plugins/processors/test_serial.py @@ -25,7 +25,7 @@ def failing_task_complex(task): a_task_for_testing(task, command="failme") -class TestSerialRunner(object): +class TestSerialRunner: def test_blocking_task_single_thread(self, nornir): t1 = datetime.datetime.now() nornir.with_runner(SerialRunner()).run(blocking_task, wait=0.5) diff --git a/tests/plugins/processors/test_threaded.py b/tests/plugins/processors/test_threaded.py index 2a0dfb08..b0974c6d 100644 --- a/tests/plugins/processors/test_threaded.py +++ b/tests/plugins/processors/test_threaded.py @@ -38,7 +38,7 @@ def verify_data_change(task): assert task.host["my_changed_var"] == task.host.name -class Test(object): +class Test: def test_blocking_task_multithreading(self, nornir): t1 = datetime.datetime.now() nornir.with_runner(ThreadedRunner(num_workers=NUM_WORKERS)).run(blocking_task, wait=2) From fff68b2012efcc3e632751cdb856005d730ffb7b Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sun, 30 Jun 2024 19:17:17 +0200 Subject: [PATCH 27/50] Move section for commented out code, remove shebang (#949) --- docs/conf.py | 1 - pyproject.toml | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 47b1b225..84aa4b32 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # nornir documentation build configuration file, created by diff --git a/pyproject.toml b/pyproject.toml index 64059753..a28770b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,8 +135,6 @@ ignore = [ "B028", # No explicit `stacklevel` keyword argument found "C419", # Unnecessary list comprehension "COM812", # Trailing comma missing - "ERA001", # Found commented-out code - "EXE001", # Shebang is present but file is not executable "FBT001", # Boolean-typed positional argument in function definition "FBT002", # Boolean default positional argument in function definition "FURB101", # `open` and `read` should be replaced by `Path(filename).read_text()` @@ -196,7 +194,8 @@ max-returns = 11 [tool.ruff.lint.per-file-ignores] "docs/conf.py" = [ - "A001", # Variable `copyright` is shadowing a Python builtin + "A001", # Variable `copyright` is shadowing a Python builtin + "ERA001", # Commented out code, used to provide examples for Sphinx docs ] "docs/highlighter.py" = [ From a3041000a0821d19efb1bf77e3fc917de92d38c6 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Sun, 30 Jun 2024 19:33:27 +0200 Subject: [PATCH 28/50] Fix highlighter typehints and use correct import path (#943) --- docs/highlighter.py | 4 ++-- pyproject.toml | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/highlighter.py b/docs/highlighter.py index 5ece78a4..bb14693c 100644 --- a/docs/highlighter.py +++ b/docs/highlighter.py @@ -1,5 +1,5 @@ +from IPython.core.display import HTML from IPython.core.magic import register_line_magic -from IPython.display import HTML from pygments import highlight from pygments.formatters import HtmlFormatter from pygments.lexers import get_lexer_for_filename @@ -17,7 +17,7 @@ @register_line_magic -def highlight_file(filename): +def highlight_file(filename: str) -> HTML: lexer = get_lexer_for_filename(filename) linenos = "inline" diff --git a/pyproject.toml b/pyproject.toml index a28770b3..a57b6014 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -171,7 +171,6 @@ ignore = [ "UP015", # Unnecessary open mode parameters "UP032", # Use f-string instead of `format` call "UP034", # Avoid extraneous parentheses - #"UP037", # Remove quotes from type annotation ] [tool.ruff.format] @@ -198,11 +197,6 @@ max-returns = 11 "ERA001", # Commented out code, used to provide examples for Sphinx docs ] -"docs/highlighter.py" = [ - "ANN001", # Missing type annotation for function argument - "ANN201", # Missing return type annotation for public function -] - "nornir/core/configuration.py" = [ "A002", # Argument `format` / `help` is shadowing a Python builtin ] From 859354b43383e57de2f72a2429cbadc2062134e7 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:11:11 +0200 Subject: [PATCH 29/50] Remove obsolete noqa statements (#944) --- nornir/core/__init__.py | 2 +- nornir/core/configuration.py | 2 +- nornir/core/exceptions.py | 2 +- pyproject.toml | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 4146f3d8..56a056d0 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -144,7 +144,7 @@ def run( raise_on_error = ( raise_on_error if raise_on_error is not None else self.config.core.raise_on_error - ) # noqa + ) if raise_on_error: result.raise_on_error() else: diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 357d9b30..9705345e 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -149,7 +149,7 @@ def configure(self) -> None: "This can lead to unexpected logging results. " "Please set logging.enabled config to False " "to disable automatic Nornir logging configuration. Refer to " - "https://nornir.readthedocs.io/en/stable/configuration/index.html#logging" # noqa + "https://nornir.readthedocs.io/en/stable/configuration/index.html#logging" ) warnings.warn(msg, ConflictingConfigurationWarning) diff --git a/nornir/core/exceptions.py b/nornir/core/exceptions.py index 01599bb1..5a20e87d 100644 --- a/nornir/core/exceptions.py +++ b/nornir/core/exceptions.py @@ -2,7 +2,7 @@ if TYPE_CHECKING: from nornir.core.connection import Connection - from nornir.core.result import AggregatedResult, MultiResult, Result # noqa + from nornir.core.result import AggregatedResult, MultiResult, Result from nornir.core.tasks import Task diff --git a/pyproject.toml b/pyproject.toml index a57b6014..13000aaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -157,7 +157,6 @@ ignore = [ "RSE102", # Unnecessary parentheses on raised exception "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "RUF100", # Unused blanket `noqa` directive "S701", # By default, jinja2 sets `autoescape` to `False`. Consider using `autoescape=True` or the `select_autoescape` function to mitigate XSS vulnerabilities. "SLF001", # Private member accessed "SIM108", # Use ternary operator `config = Config.from_file(config_file, **kwargs) if config_file else Config.from_dict(**kwargs)` instead of `if`-`else`-block From f6aa5ec4ea800963527a944292fd474d0baec89b Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:11:47 +0200 Subject: [PATCH 30/50] Fix Ruff TRY300: Consider moving this statement to an `else` block (#946) --- nornir/core/inventory.py | 3 +-- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index f2615002..715b5263 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -339,8 +339,7 @@ def __getitem__(self, item: str) -> Any: except KeyError: for g in self.extended_groups(): try: - r = g.data[item] - return r + return g.data[item] except KeyError: continue diff --git a/pyproject.toml b/pyproject.toml index 13000aaa..c557661c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,7 +164,6 @@ ignore = [ "TRY002", # Create your own exception "TRY003", # Avoid specifying long messages outside the exception class "TRY004", # Prefer `TypeError` exception for invalid type - "TRY300", # Consider moving this statement to an `else` block "TRY400", # Use `logging.exception` instead of `logging.error` "UP009", # UTF-8 encoding declaration is unnecessary "UP015", # Unnecessary open mode parameters From e77da8996e030351b125b1cb4cc83c217ab41dcb Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:12:00 +0200 Subject: [PATCH 31/50] Upgrade mypy (#948) --- poetry.lock | 70 +++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/poetry.lock b/poetry.lock index 793eed00..2df12a2a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alabaster" @@ -1419,16 +1419,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1488,38 +1478,38 @@ files = [ [[package]] name = "mypy" -version = "1.5.1" +version = "1.10.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"}, - {file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"}, - {file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"}, - {file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"}, - {file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"}, - {file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"}, - {file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"}, - {file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"}, - {file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"}, - {file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"}, - {file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"}, - {file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"}, - {file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"}, - {file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"}, - {file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"}, - {file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"}, - {file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"}, - {file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"}, - {file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"}, - {file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"}, - {file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"}, - {file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"}, - {file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"}, - {file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"}, - {file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"}, - {file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"}, - {file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, + {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"}, + {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"}, + {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"}, + {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"}, + {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"}, + {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"}, + {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"}, + {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"}, + {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"}, + {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"}, + {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"}, + {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"}, + {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"}, + {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"}, + {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"}, + {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"}, + {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"}, ] [package.dependencies] @@ -1530,6 +1520,7 @@ typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] @@ -2325,7 +2316,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, From 8fb80594e5239bd1c7ce4548003a12277902baaa Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:12:13 +0200 Subject: [PATCH 32/50] Remove obsolete encoding declaration (#950) --- docs/conf.py | 2 -- pyproject.toml | 1 - 2 files changed, 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 84aa4b32..df5cb207 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # nornir documentation build configuration file, created by # sphinx-quickstart on Sun Nov 19 10:41:40 2017. # diff --git a/pyproject.toml b/pyproject.toml index c557661c..fc170615 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,7 +165,6 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class "TRY004", # Prefer `TypeError` exception for invalid type "TRY400", # Use `logging.exception` instead of `logging.error` - "UP009", # UTF-8 encoding declaration is unnecessary "UP015", # Unnecessary open mode parameters "UP032", # Use f-string instead of `format` call "UP034", # Avoid extraneous parentheses From cd47bdcfff717bb1bdef73a74cc9e6e91d270d09 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:12:25 +0200 Subject: [PATCH 33/50] Move mypy config to pyproject.toml (#951) --- pyproject.toml | 21 +++++++++++++++++++++ setup.cfg | 20 -------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fc170615..16a83811 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,27 @@ nbsphinx = "0.9.2" pygments = "2.16.1" sphinx-issues = "3.0.1" +[tool.mypy] +# The mypy configurations: http://bit.ly/2zEl9WI +python_version = "3.8" +check_untyped_defs = true +disallow_any_generics = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +ignore_errors = false +ignore_missing_imports = true +strict_optional = true +warn_unused_configs = true +warn_unused_ignores = true +warn_return_any = true +warn_redundant_casts = true + +[[tool.mypy.overrides]] +module = "tests.*" +ignore_errors = true + [tool.ruff] line-length = 100 diff --git a/setup.cfg b/setup.cfg index e538fc17..a2a761f0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,23 +8,3 @@ universal=1 #addopts = --cov=nornir --cov-report=term-missing -vs filterwarnings = ignore::nornir.core.exceptions.ConflictingConfigurationWarning - -[mypy] -# The mypy configurations: http://bit.ly/2zEl9WI -python_version = 3.8 -check_untyped_defs = True -disallow_any_generics = True -disallow_untyped_calls = True -disallow_untyped_defs = True -disallow_incomplete_defs = True -disallow_untyped_decorators = True -ignore_errors = False -ignore_missing_imports = True -strict_optional = True -warn_unused_configs = True -warn_unused_ignores = True -warn_return_any = True -warn_redundant_casts = True - -[mypy-tests.*] -ignore_errors = True From 66591361a06305e34885d515e8694dbd13b5cf33 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:12:38 +0200 Subject: [PATCH 34/50] Add missing return type annotation for special method `__init__ (#952) Fix Ruff - ANN204 --- nornir/core/exceptions.py | 2 +- nornir/core/task.py | 8 ++++---- pyproject.toml | 1 - tests/core/test_InitNornir.py | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/nornir/core/exceptions.py b/nornir/core/exceptions.py index 5a20e87d..0bf1bc66 100644 --- a/nornir/core/exceptions.py +++ b/nornir/core/exceptions.py @@ -75,7 +75,7 @@ class NornirSubTaskError(Exception): Raised by nornir when a sub task managed by :meth:`nornir.core.Task.run` has failed """ - def __init__(self, task: "Task", result: "Result"): + def __init__(self, task: "Task", result: "Result") -> None: self.task = task self.result = result diff --git a/nornir/core/task.py b/nornir/core/task.py index b7bb2f1d..3a53a6ca 100644 --- a/nornir/core/task.py +++ b/nornir/core/task.py @@ -48,7 +48,7 @@ def __init__( severity_level: int = DEFAULT_SEVERITY_LEVEL, parent_task: Optional["Task"] = None, **kwargs: str, - ): + ) -> None: self.task = task self.nornir = nornir self.name = name or task.__name__ @@ -214,7 +214,7 @@ def __init__( exception: Optional[BaseException] = None, severity_level: int = DEFAULT_SEVERITY_LEVEL, **kwargs: Any, - ): + ) -> None: self.result = result self.host = host self.changed = changed @@ -246,7 +246,7 @@ class MultiResult(List[Result]): a particular device/task. """ - def __init__(self, name: str): + def __init__(self, name: str) -> None: self.name = name def __getattr__(self, name: str) -> Any: @@ -280,7 +280,7 @@ class AggregatedResult(Dict[str, MultiResult]): You can access each individual result by doing ``my_aggr_result["hostname_of_device"]``. """ - def __init__(self, name: str, **kwargs: MultiResult): + def __init__(self, name: str, **kwargs: MultiResult) -> None: self.name = name super().__init__(**kwargs) diff --git a/pyproject.toml b/pyproject.toml index 16a83811..f727e821 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -150,7 +150,6 @@ ignore = [ # like this so that we can reactivate them one by one. Alternatively ignored after further # # investigation if they are deemed to not make sense. # ################################################################################################## - "ANN204", # Missing return type annotation for special method `__init__` "ANN401", # Dynamically typed expressions (typing.Any) are disallowed "ARG002", # Unused method argument "B028", # No explicit `stacklevel` keyword argument found diff --git a/tests/core/test_InitNornir.py b/tests/core/test_InitNornir.py index ba533b5a..745eab09 100644 --- a/tests/core/test_InitNornir.py +++ b/tests/core/test_InitNornir.py @@ -45,7 +45,7 @@ def transform_func_with_options(host, a): class InventoryTest: - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: pass def load(self): From 7cf64639ad350c9d2c3798dcc14324ea1d1ee28d Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:12:53 +0200 Subject: [PATCH 35/50] Remove unnecessary list comprehension (#953) --- nornir/core/filter.py | 6 +++--- nornir/core/inventory.py | 4 ++-- nornir/core/task.py | 6 +++--- pyproject.toml | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/nornir/core/filter.py b/nornir/core/filter.py index eb0db82a..e9d37b7e 100644 --- a/nornir/core/filter.py +++ b/nornir/core/filter.py @@ -90,12 +90,12 @@ def _verify_rules(data: Any, rule: List[str], value: Any) -> bool: if rule == ["any"]: if isinstance(data, list): - return any([x in data for x in value]) - return any([x == data for x in value]) + return any(x in data for x in value) + return any(x == data for x in value) if rule == ["all"]: if isinstance(data, list): - return all([x in data for x in value]) + return all(x in data for x in value) # it doesn't make sense to check a single value meets more than one case return False diff --git a/nornir/core/inventory.py b/nornir/core/inventory.py index 715b5263..5a329f4c 100644 --- a/nornir/core/inventory.py +++ b/nornir/core/inventory.py @@ -95,9 +95,9 @@ def dict(self) -> Dict[str, Any]: class ParentGroups(List["Group"]): def __contains__(self, value: object) -> bool: if isinstance(value, str): - return any([value == g.name for g in self]) + return any(value == g.name for g in self) - return any([value == g for g in self]) + return any(value == g for g in self) def add(self, group: "Group") -> None: """ diff --git a/nornir/core/task.py b/nornir/core/task.py index 3a53a6ca..ba13fd40 100644 --- a/nornir/core/task.py +++ b/nornir/core/task.py @@ -258,12 +258,12 @@ def __repr__(self) -> str: @property def failed(self) -> bool: """If ``True`` at least a task failed.""" - return any([h.failed for h in self]) + return any(h.failed for h in self) @property def changed(self) -> bool: """If ``True`` at least a task changed the system.""" - return any([h.changed for h in self]) + return any(h.changed for h in self) def raise_on_error(self) -> None: """ @@ -290,7 +290,7 @@ def __repr__(self) -> str: @property def failed(self) -> bool: """If ``True`` at least a host failed.""" - return any([h.failed for h in self.values()]) + return any(h.failed for h in self.values()) @property def failed_hosts(self) -> Dict[str, "MultiResult"]: diff --git a/pyproject.toml b/pyproject.toml index f727e821..9243b50e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -153,7 +153,6 @@ ignore = [ "ANN401", # Dynamically typed expressions (typing.Any) are disallowed "ARG002", # Unused method argument "B028", # No explicit `stacklevel` keyword argument found - "C419", # Unnecessary list comprehension "COM812", # Trailing comma missing "FBT001", # Boolean-typed positional argument in function definition "FBT002", # Boolean default positional argument in function definition From 03b576af27cf5c6377ea985765f247d66444891f Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:13:06 +0200 Subject: [PATCH 36/50] Fix Ruff PYI036 - Type annotations for context manager exit (#954) The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None --- nornir/core/__init__.py | 4 ++-- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 56a056d0..3234633a 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -51,8 +51,8 @@ def __enter__(self) -> "Nornir": def __exit__( self, - exc_type: Type[BaseException], - exc_val: BaseException, + exc_type: Optional[Type[BaseException]] = None, + exc_val: Optional[BaseException] = None, exc_tb: Optional[types.TracebackType] = None, ) -> None: self.close_connections(on_good=True, on_failed=True) diff --git a/pyproject.toml b/pyproject.toml index 9243b50e..aeb52315 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -171,7 +171,6 @@ ignore = [ "PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()` "PTH120", # `os.path.dirname()` should be replaced by `Path.parent` "PTH123", # `open()` should be replaced by `Path.open()` - "PYI036", # The first argument in `__exit__` should be annotated with `object` or `type[BaseException] | None` "RET504", # Unnecessary assignment before `return` statement "RSE102", # Unnecessary parentheses on raised exception "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? From 6d9f37bd42142339dc36958c8b96b8ac02bfbbdc Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:13:20 +0200 Subject: [PATCH 37/50] Rewrite tests to avoid Yoda conditions (#955) --- pyproject.toml | 1 - tests/core/test_inventory.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index aeb52315..0f917d55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -259,6 +259,5 @@ max-returns = 11 "PT018", # Assertion should be broken down into multiple parts "PT011", # `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception "SIM118", # Use `key in dict` instead of `key in dict.keys()` - "SIM300", # Yoda conditions are discouraged ] diff --git a/tests/core/test_inventory.py b/tests/core/test_inventory.py index 4f9563d1..6219b6e5 100644 --- a/tests/core/test_inventory.py +++ b/tests/core/test_inventory.py @@ -65,7 +65,7 @@ def test_inventory_data(self, inv): assert "blah" in h.values() assert "my_var" in h.keys() assert "only_default" in h.keys() - assert "comes_from_dev1.group_1" == dict(h.items())["my_var"] + assert dict(h.items())["my_var"] == "comes_from_dev1.group_1" def test_inventory_dict(self, inv): assert inv.dict() == { @@ -561,7 +561,7 @@ def test_add_group(self): assert inv.groups["g3"].defaults.connection_options.get("username") == "test_user" assert inv.groups["g3"].defaults.connection_options.get("password") == "test_pass" assert "test_var" in inv.groups["g3"].defaults.data.keys() - assert "test_value" == inv.groups["g3"].defaults.data.get("test_var") + assert inv.groups["g3"].defaults.data.get("test_var") == "test_value" assert inv.groups["g3"].connection_options["netmiko"].extras["device_type"] == "cisco_ios" def test_dict(self, inv): From 9d9c5df3a20bc59a3db24bab4ccdaf1ee82c331a Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 09:13:31 +0200 Subject: [PATCH 38/50] Rename name -> hostname to avoid redefining argument with the local name (#956) Fixes Ruff: PLR1704 --- nornir/core/__init__.py | 8 ++++---- pyproject.toml | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index 3234633a..354ef443 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -121,12 +121,12 @@ def run( run_on = [] if on_good: - for name, host in self.inventory.hosts.items(): - if name not in self.data.failed_hosts: + for hostname, host in self.inventory.hosts.items(): + if hostname not in self.data.failed_hosts: run_on.append(host) if on_failed: - for name, host in self.inventory.hosts.items(): - if name in self.data.failed_hosts: + for hostname, host in self.inventory.hosts.items(): + if hostname in self.data.failed_hosts: run_on.append(host) num_hosts = len(run_on) diff --git a/pyproject.toml b/pyproject.toml index 0f917d55..6669cdb6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -163,7 +163,6 @@ ignore = [ "PIE800", # Unnecessary spread `**` "PLC0205", # Class `__slots__` should be a non-string iterable "PLC2801", # Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function - "PLR1704", # Redefining argument with the local name "PLR6201", # Use a `set` literal when testing for membership "PLR6301", # Method `run` could be a function, class method, or static method "PLW1514", # `open` in text mode without explicit `encoding` argument From a9f90dec00425fac731cf2089c1d363506ebb37e Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 13:31:43 +0200 Subject: [PATCH 39/50] Remove sponsor link as it was already disabled (#957) --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index d1ad7fc9..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [dbarrosop] From dcdc34e7f1a2ab8006a421ab379e34e6ac2985c2 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 13:32:08 +0200 Subject: [PATCH 40/50] Fix PLC0205: Class `__slots__` should be a non-string iterable (#945) --- nornir/core/configuration.py | 2 +- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/nornir/core/configuration.py b/nornir/core/configuration.py index 9705345e..543d2bc1 100644 --- a/nornir/core/configuration.py +++ b/nornir/core/configuration.py @@ -211,7 +211,7 @@ def dict(self) -> Dict[str, Any]: class CoreConfig: - __slots__ = "raise_on_error" + __slots__ = ("raise_on_error",) class Parameters: raise_on_error = Parameter(default=False, envvar="NORNIR_CORE_RAISE_ON_ERROR") diff --git a/pyproject.toml b/pyproject.toml index 6669cdb6..a0d34149 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -161,7 +161,6 @@ ignore = [ "PERF203", # `try`-`except` within a loop incurs performance overhead "PGH004", # Use specific rule codes when using `noqa` "PIE800", # Unnecessary spread `**` - "PLC0205", # Class `__slots__` should be a non-string iterable "PLC2801", # Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function "PLR6201", # Use a `set` literal when testing for membership "PLR6301", # Method `run` could be a function, class method, or static method From 0d03b6edc2a1e28f98c6c807b3dd7a5c6dbb38d2 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 1 Jul 2024 20:53:26 +0200 Subject: [PATCH 41/50] Remove unnecessary assignment before `return` statement (#958) --- nornir/init_nornir.py | 3 +-- pyproject.toml | 1 - tests/conftest.py | 7 ++----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/nornir/init_nornir.py b/nornir/init_nornir.py index 7de8f8a4..314c0eca 100644 --- a/nornir/init_nornir.py +++ b/nornir/init_nornir.py @@ -35,8 +35,7 @@ def load_runner( ) -> RunnerPlugin: RunnersPluginRegister.auto_register() runner_plugin = RunnersPluginRegister.get_plugin(config.runner.plugin) - runner = runner_plugin(**config.runner.options) - return runner + return runner_plugin(**config.runner.options) def InitNornir( diff --git a/pyproject.toml b/pyproject.toml index a0d34149..2417c8ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -169,7 +169,6 @@ ignore = [ "PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()` "PTH120", # `os.path.dirname()` should be replaced by `Path.parent` "PTH123", # `open()` should be replaced by `Path.open()` - "RET504", # Unnecessary assignment before `return` statement "RSE102", # Unnecessary parentheses on raised exception "RUF001", # String contains ambiguous `–` (EN DASH). Did you mean `-` (HYPHEN-MINUS)? "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` diff --git a/tests/conftest.py b/tests/conftest.py index 3cd2b7b1..f3f389b9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -43,7 +43,7 @@ def get_defaults(): with open(defaults_file, "r") as f: defaults_dict = yml.load(f) - defaults = Defaults( + return Defaults( hostname=defaults_dict.get("hostname"), port=defaults_dict.get("port"), username=defaults_dict.get("username"), @@ -55,8 +55,6 @@ def get_defaults(): ), ) - return defaults - def get_inventory_element(typ, data, name, defaults): return typ( name=name, @@ -124,8 +122,7 @@ def inv(request): @pytest.fixture(scope="session", autouse=True) def nornir(request): """Initializes nornir""" - nr = Nornir(inventory=inventory_from_yaml(), runner=SerialRunner(), data=global_data) - return nr + return Nornir(inventory=inventory_from_yaml(), runner=SerialRunner(), data=global_data) @pytest.fixture(scope="function", autouse=True) From 11408c00cc7b2acb49682097767c82448ad91694 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:16:43 +0200 Subject: [PATCH 42/50] Bump cryptography from 41.0.4 to 42.0.4 (#898) Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.4 to 42.0.4. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.4...42.0.4) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 84 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2df12a2a..8a13c20b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -536,47 +536,56 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.4" +version = "42.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, - {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, - {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, - {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, -] - -[package.dependencies] -cffi = ">=1.12" + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b"}, + {file = "cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925"}, + {file = "cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923"}, + {file = "cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0"}, + {file = "cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129"}, + {file = "cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660"}, + {file = "cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1419,6 +1428,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2316,6 +2335,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, From 3f2d79fb443e07aaaf2f634e4f43b3c4f20e5d14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:28:09 +0200 Subject: [PATCH 43/50] Bump jinja2 from 3.1.2 to 3.1.4 (#906) Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.4. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.4) --- updated-dependencies: - dependency-name: jinja2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8a13c20b..9efd9036 100644 --- a/poetry.lock +++ b/poetry.lock @@ -920,13 +920,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] From 4ac6a3339d557dad2b3cad4341e1e072b8cf6f1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:39:31 +0200 Subject: [PATCH 44/50] Bump jupyter-server from 2.7.3 to 2.11.2 (#883) Bumps [jupyter-server](https://github.com/jupyter-server/jupyter_server) from 2.7.3 to 2.11.2. - [Release notes](https://github.com/jupyter-server/jupyter_server/releases) - [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md) - [Commits](https://github.com/jupyter-server/jupyter_server/compare/v2.7.3...v2.11.2) --- updated-dependencies: - dependency-name: jupyter-server dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9efd9036..2cd631ee 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1120,13 +1120,13 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-events" -version = "0.7.0" +version = "0.10.0" description = "Jupyter Event System library" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_events-0.7.0-py3-none-any.whl", hash = "sha256:4753da434c13a37c3f3c89b500afa0c0a6241633441421f6adafe2fb2e2b924e"}, - {file = "jupyter_events-0.7.0.tar.gz", hash = "sha256:7be27f54b8388c03eefea123a4f79247c5b9381c49fb1cd48615ee191eb12615"}, + {file = "jupyter_events-0.10.0-py3-none-any.whl", hash = "sha256:4b72130875e59d57716d327ea70d3ebc3af1944d3717e5a498b8a06c6c159960"}, + {file = "jupyter_events-0.10.0.tar.gz", hash = "sha256:670b8229d3cc882ec782144ed22e0d29e1c2d639263f92ca8383e66682845e22"}, ] [package.dependencies] @@ -1160,13 +1160,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.7.3" +version = "2.11.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.7.3-py3-none-any.whl", hash = "sha256:8e4b90380b59d7a1e31086c4692231f2a2ea4cb269f5516e60aba72ce8317fc9"}, - {file = "jupyter_server-2.7.3.tar.gz", hash = "sha256:d4916c8581c4ebbc534cebdaa8eca2478d9f3bfdd88eae29fcab0120eac57649"}, + {file = "jupyter_server-2.11.2-py3-none-any.whl", hash = "sha256:0c548151b54bcb516ca466ec628f7f021545be137d01b5467877e87f6fff4374"}, + {file = "jupyter_server-2.11.2.tar.gz", hash = "sha256:0c99f9367b0f24141e527544522430176613f9249849be80504c6d2b955004bb"}, ] [package.dependencies] @@ -1175,7 +1175,7 @@ argon2-cffi = "*" jinja2 = "*" jupyter-client = ">=7.4.4" jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -jupyter-events = ">=0.6.0" +jupyter-events = ">=0.9.0" jupyter-server-terminals = "*" nbconvert = ">=6.4.4" nbformat = ">=5.3.0" From 029ab0275f22cf4c4f50936b3a494910ef6d2e6b Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Tue, 2 Jul 2024 20:57:28 +0200 Subject: [PATCH 45/50] Remove ruff ignore rule that was fixed in a previous PR (#959) --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2417c8ac..8c8ae451 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -159,7 +159,6 @@ ignore = [ "FURB101", # `open` and `read` should be replaced by `Path(filename).read_text()` "INP001", # File is part of an implicit namespace package. Add an `__init__.py`. "PERF203", # `try`-`except` within a loop incurs performance overhead - "PGH004", # Use specific rule codes when using `noqa` "PIE800", # Unnecessary spread `**` "PLC2801", # Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function "PLR6201", # Use a `set` literal when testing for membership From faecd6ccb11e52243b60ae85eda39cf957f10da9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Jul 2024 07:49:27 +0200 Subject: [PATCH 46/50] Bump certifi from 2023.7.22 to 2024.7.4 (#960) Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.7.22 to 2024.7.4. - [Commits](https://github.com/certifi/python-certifi/compare/2023.07.22...2024.07.04) --- updated-dependencies: - dependency-name: certifi dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2cd631ee..6c06efd5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alabaster" @@ -265,13 +265,13 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] From e8d2eeecde6d09341ae42bbdd22324159bced02f Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Thu, 11 Jul 2024 08:36:11 +0200 Subject: [PATCH 47/50] Reactivate coveralls (#964) --- .github/workflows/main.yaml | 4 ++++ Makefile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 70f2721f..e02b2398 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -93,6 +93,10 @@ jobs: run: make nbval if: ${{ matrix.platform != 'windows-2019' }} + - name: Report coverage + uses: coverallsapp/github-action@v2 + if: ${{ matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.11' }} + # release: # name: Releasing to pypi # runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 0c8f5c62..154e205c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ docker: .PHONY: pytest pytest: - poetry run pytest --cov=nornir --cov-report=term-missing -vs ${ARGS} + poetry run pytest --cov=nornir --cov-report=term-missing --cov-report xml -vs ${ARGS} .PHONY: mypy mypy: From 9cc71029def1755d92c02eadc77e8eef157f5e10 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Thu, 11 Jul 2024 16:53:02 +0200 Subject: [PATCH 48/50] Add Python 3.12 to test matrix (#961) --- .github/workflows/main.yaml | 2 +- docs/howto/filtering_deep_dive.ipynb | 6 ++-- poetry.lock | 50 ++++++++++------------------ pyproject.toml | 3 +- 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index e02b2398..648c1d40 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -52,7 +52,7 @@ jobs: shell: bash strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11' ] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ] platform: [ubuntu-latest, macos-13, windows-2019] runs-on: ${{ matrix.platform }} steps: diff --git a/docs/howto/filtering_deep_dive.ipynb b/docs/howto/filtering_deep_dive.ipynb index 389d55b1..1a7826b2 100644 --- a/docs/howto/filtering_deep_dive.ipynb +++ b/docs/howto/filtering_deep_dive.ipynb @@ -2056,7 +2056,7 @@ " :return bool: True if it matches, False if it doesn't match\n", " \"\"\"\n", " # Perform regex match on host name and return boolean\n", - " if re.match(\".+\\-[0-9][2,4,6,8,0].+\", host.name):\n", + " if re.match(r\".*-\\d[24680].*\", host.name):\n", " return True\n", " else:\n", " return False\n", @@ -2074,7 +2074,7 @@ " :return bool: True if it matches, False if it doesn't match\n", " \"\"\"\n", " # Perform regex match on host name and return boolean\n", - " if re.match(\"\\w{3}\\-\\w+\\-\\d{2}.\\w{3}.norn.local\", host.name):\n", + " if re.match(r\"\\w{3}-\\w+-\\d{2}\\.\\w{3}\\.norn\\.local\", host.name):\n", " return True\n", " else:\n", " return False\n", @@ -2092,7 +2092,7 @@ " :return bool: True if does not match, False if it matches the convention\n", " \"\"\"\n", " # Perform regex match on host name and return boolean\n", - " if re.match(\"\\w{3}\\-\\w+\\-\\d{2}.\\w{3}.norn.local\", host.name):\n", + " if re.match(r\"\\w{3}-\\w+-\\d{2}\\.\\w{3}\\.norn\\.local\", host.name):\n", " return False\n", " else:\n", " return True\n", diff --git a/poetry.lock b/poetry.lock index 6c06efd5..f6755465 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1008,21 +1008,19 @@ referencing = ">=0.28.0" [[package]] name = "junos-eznc" -version = "2.6.7" +version = "2.7.1" description = "Junos 'EZ' automation for non-programmers" optional = false -python-versions = ">=3.5, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "junos-eznc-2.6.7.tar.gz", hash = "sha256:b3ab81dafb160cd16cba8f26b92b6f5c3333a8d30566a7ebd966fc1f313b0980"}, - {file = "junos_eznc-2.6.7-py2.py3-none-any.whl", hash = "sha256:6ee9d74228ebaca01381eb88dbe21765006d76935960fd4e6cd8d67248b11644"}, + {file = "junos-eznc-2.7.1.tar.gz", hash = "sha256:371f0298bf03e0cb4c017c43f6f4122263584eda0d690d0112e93f13daae41ac"}, + {file = "junos_eznc-2.7.1-py3-none-any.whl", hash = "sha256:8a7918faa8f0570341cac64c1210c1cd3e3542162d1e7449c3364f8d805716b2"}, ] [package.dependencies] jinja2 = ">=2.7.1" lxml = ">=3.2.4" -ncclient = "0.6.13" -netaddr = "*" -paramiko = ">=1.15.2" +ncclient = ">=0.6.15" pyparsing = "*" pyserial = "*" PyYAML = ">=5.1" @@ -1428,16 +1426,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1555,27 +1543,26 @@ files = [ [[package]] name = "napalm" -version = "4.1.0" +version = "5.0.0" description = "Network Automation and Programmability Abstraction Layer with Multivendor support" optional = false python-versions = "*" files = [ - {file = "napalm-4.1.0-py2.py3-none-any.whl", hash = "sha256:14a5b7759a0247a26fff2c444b1cfc150a08224de8addf4076c384845285bf5b"}, - {file = "napalm-4.1.0.tar.gz", hash = "sha256:3b3e18efd556861c056ba509eb46f5ffc9e3e6c42db399fa76b6ea9af272c17a"}, + {file = "napalm-5.0.0-py2.py3-none-any.whl", hash = "sha256:458837932e527ca06a4bab7e600b0ca6e6bc3bb4b33fad9c9ef2befc7df6d2f5"}, + {file = "napalm-5.0.0.tar.gz", hash = "sha256:350ac3d74f2f10030dbae44d3395551d7e03ee25c65fa5eb8263a4e6f51f2c94"}, ] [package.dependencies] cffi = ">=1.11.3" -future = "*" jinja2 = "*" -junos-eznc = ">=2.6.3" +junos-eznc = ">=2.7.0" lxml = ">=4.3.0" ncclient = "*" netaddr = "*" netmiko = ">=4.1.0" netutils = ">=1.0.0" paramiko = ">=2.6.0" -pyeapi = ">=0.8.2" +pyeapi = ">=1.0.2" pyYAML = "*" requests = ">=2.7.0" scp = "*" @@ -1705,12 +1692,12 @@ pytest = ">=2.8" [[package]] name = "ncclient" -version = "0.6.13" +version = "0.6.15" description = "Python library for NETCONF clients" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "ncclient-0.6.13.tar.gz", hash = "sha256:f9f8cea8bcbe057e1b948b9cd1b241eafb8a3f73c4981fbdfa1cc6ed69c0a7b3"}, + {file = "ncclient-0.6.15.tar.gz", hash = "sha256:6757cb41bc9160dfe47f22f5de8cf2f1adf22f27463fb50453cc415ab96773d8"}, ] [package.dependencies] @@ -1791,17 +1778,17 @@ nornir = ">=3,<4" [[package]] name = "nornir-napalm" -version = "0.4.0" +version = "0.5.0" description = "NAPALM's plugins for nornir" optional = false -python-versions = ">=3.7,<4.0" +python-versions = "<4.0,>=3.8" files = [ - {file = "nornir_napalm-0.4.0-py3-none-any.whl", hash = "sha256:20a41499aecf9c4e41181b18a73b2ee3ab7763824645ac0eb80abb3973a5f17e"}, - {file = "nornir_napalm-0.4.0.tar.gz", hash = "sha256:84e0711ccbdf24bdb228042ab530bf688d6b2b8f12c65fa3cb73499c6974a9de"}, + {file = "nornir_napalm-0.5.0-py3-none-any.whl", hash = "sha256:1a418bf0f5e38ac65894d474f81b50787dafe0aa1965c4fbd1b86d34d4374418"}, + {file = "nornir_napalm-0.5.0.tar.gz", hash = "sha256:4c95979eebe2475e7b8516411ad8e3205d2ff30e410d1dbdce785a55033d1130"}, ] [package.dependencies] -napalm = ">=4,<5" +napalm = ">=5,<6" nornir = ">=3,<4" [[package]] @@ -2335,7 +2322,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3428,4 +3414,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "37134dc424f8169de36942d71513d6914ab0866c5fedaebc0c3a074a0279b697" +content-hash = "6919ce4f6522959be69c5cfecd21c90a920d57e4581b1435972a92e171d3feb0" diff --git a/pyproject.toml b/pyproject.toml index 8c8ae451..fe637f82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] [tool.poetry.dependencies] @@ -43,7 +44,7 @@ types-Jinja2 = "^2.11.9" types-pkg-resources = "^0.1.3" nornir-jinja2 = "0.2.0" nornir-utils = "0.2.0" -nornir-napalm = "0.4.0" +nornir-napalm = "0.5.0" ruff = "^0.4.9" [tool.poetry.group.docs.dependencies] From f35c1eab850159d33507c54dc0679c1f5dc4f966 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 12 Jul 2024 07:51:03 +0200 Subject: [PATCH 49/50] Switch coverage badge from develop to main branch (#965) This is to reflect the current default branch on GitHub where the `develop` branch no longer exists. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ce533ad..3d273a74 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build Status](https://github.com/nornir-automation/nornir/workflows/test%20nornir/badge.svg) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Coverage Status](https://coveralls.io/repos/github/nornir-automation/nornir/badge.svg?branch=develop)](https://coveralls.io/github/nornir-automation/nornir?branch=develop) +![Build Status](https://github.com/nornir-automation/nornir/workflows/test%20nornir/badge.svg) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Coverage Status](https://coveralls.io/repos/github/nornir-automation/nornir/badge.svg?branch=main)](https://coveralls.io/github/nornir-automation/nornir?branch=main) Nornir From d8e82d4c959d3ae43fc4a9c9a51737e71e77e871 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Tue, 23 Jul 2024 20:11:37 +0200 Subject: [PATCH 50/50] Simlify _verify_rules and redunce max-complexity=10 (#962) Co-authored-by: David Barroso --- nornir/core/filter.py | 54 +++++++++++++++++++++++-------------------- pyproject.toml | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/nornir/core/filter.py b/nornir/core/filter.py index e9d37b7e..5c16c33b 100644 --- a/nornir/core/filter.py +++ b/nornir/core/filter.py @@ -68,39 +68,43 @@ def __eq__(self, other: object) -> bool: return self.__class__ == other.__class__ and self.filters == other.filters @staticmethod - def _verify_rules(data: Any, rule: List[str], value: Any) -> bool: - if len(rule) > 1: - try: - return F._verify_rules(data.get(rule[0], {}), rule[1:], value) - except AttributeError: - return False + def _verify_rule(data: Any, rule: str, value: Any) -> bool: + operator = "__{}__".format(rule) + if hasattr(data, operator): + return getattr(data, operator)(value) is True - elif len(rule) == 1: - operator = "__{}__".format(rule[0]) - if hasattr(data, operator): - return getattr(data, operator)(value) is True + if hasattr(data, rule): + if callable(getattr(data, rule)): + return bool(getattr(data, rule)(value)) + return bool(getattr(data, rule) == value) + + if rule == "in": + return bool(data in value) - if hasattr(data, rule[0]): - if callable(getattr(data, rule[0])): - return bool(getattr(data, rule[0])(value)) - return bool(getattr(data, rule[0]) == value) + if rule == "any": + if isinstance(data, list): + return any(x in data for x in value) + return any(x == data for x in value) - if rule == ["in"]: - return bool(data in value) + if rule == "all": + if isinstance(data, list): + return all(x in data for x in value) - if rule == ["any"]: - if isinstance(data, list): - return any(x in data for x in value) - return any(x == data for x in value) + # it doesn't make sense to check a single value meets more than one case + return False - if rule == ["all"]: - if isinstance(data, list): - return all(x in data for x in value) + return bool(data.get(rule) == value) - # it doesn't make sense to check a single value meets more than one case + @staticmethod + def _verify_rules(data: Any, rule: List[str], value: Any) -> bool: + if len(rule) > 1: + try: + return F._verify_rules(data.get(rule[0], {}), rule[1:], value) + except AttributeError: return False - return bool(data.get(rule[0]) == value) + elif len(rule) == 1: + return F._verify_rule(data, rule[0], value) else: raise Exception("I don't know how I got here:\n{}\n{}\n{}".format(data, rule, value)) diff --git a/pyproject.toml b/pyproject.toml index fe637f82..6f0c2496 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -192,7 +192,7 @@ skip-magic-trailing-comma = false line-ending = "auto" [tool.ruff.lint.mccabe] -max-complexity = 12 +max-complexity = 10 [tool.ruff.lint.pylint]