From 7cac01b6038e05ef112b0423ba4aa8e31fcd913e Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Thu, 27 Jun 2024 11:49:03 +0200 Subject: [PATCH] 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 2c899adc4..998ee30f2 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 61a4ce166..26fa12bfb 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 f0b13e342..e28e44985 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 eb030f4b5..9ce533ad6 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 b788d0d67..fb8263d43 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 b30f17b74..449f40ac2 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 8a04c02fe..85f4e46b9 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 c6507fa63..91665f0ba 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 3b3466d3e..f2d8ad648 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 f900dbff3..524e7b350 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 1f9dca079..1537a826f 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 98bba7a1a..5b6f43089 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 3c58f36bd..4e00e6d81 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 979fe5de2..2000881d8 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 0ee0884ca..107537a71 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 32f45d8db..430da27ba 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 bc5dd92ad..52b3cdb96 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 feab13c4b..3cd2b7b1b 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 c926b634e..3c0ba3300 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 9726a912b..6d3b07a8e 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 b18eb2acb..529b4369f 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 1d84cce4b..995a865d4 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 5bede97df..eb27b6634 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 cbd61f699..3573a1655 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 38c18498f..2a0dfb083 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