From a2ca5e993db38c8df46b6c1ac899d01b92dc5b85 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Sun, 15 Oct 2023 11:42:23 -0400 Subject: [PATCH] Pivot to from flake8 to ruff for Python linting Since the start of the 0.3.x release of the retworkx project we have been using flake8 for Python linting and this has worked well for us. However, recently a new project, ruff [1][2], has shown increasing popularity becuase it provides the same linting coverage but is signficantly faster. Also just from a language solidatry PoV ruff is also written in rust. This commit migrates our linting jobs to use ruff instead of flake8 and sets up a reasonable set of rules as a starting point, which includes the rules equivalent to what we were using before with flake8, pyupgrade, and flake8-pyi, and flake8-quotes. [1] https://docs.astral.sh/ruff/ [2] https://github.com/astral-sh/ruff --- .github/workflows/main.yml | 4 +- pyproject.toml | 29 +++++++ rustworkx/digraph.pyi | 76 +++++++++---------- rustworkx/graph.pyi | 60 +++++++-------- rustworkx/iterators.pyi | 24 +++--- setup.py | 18 ++--- .../digraph/test_dot.py | 2 +- .../digraph/test_edgelist.py | 4 +- .../digraph/test_layout.py | 5 +- .../graph/test_dot.py | 2 +- .../graph/test_edgelist.py | 4 +- .../graph/test_layout.py | 5 +- .../graph/test_max_weight_matching.py | 15 ++-- .../test_custom_return_types.py | 2 +- tests/rustworkx_tests/digraph/test_dot.py | 2 +- .../rustworkx_tests/digraph/test_edgelist.py | 4 +- tests/rustworkx_tests/digraph/test_layout.py | 5 +- tests/rustworkx_tests/graph/test_dot.py | 2 +- tests/rustworkx_tests/graph/test_edgelist.py | 4 +- tests/rustworkx_tests/graph/test_layout.py | 5 +- .../graph/test_max_weight_matching.py | 15 ++-- .../test_substitute_node_with_subgraph.py | 2 +- .../test_custom_return_types.py | 2 +- tox.ini | 15 +--- 24 files changed, 154 insertions(+), 152 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b03b7a8e7..fcf605593 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: 3.8 - - run: pip install -U flake8 black~=22.0 + - run: pip install -U ruff black~=22.0 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt @@ -38,7 +38,7 @@ jobs: - name: Black Codestyle Format run: black --check --diff retworkx rustworkx retworkx tests - name: Python Lint - run: flake8 --per-file-ignores='retworkx/__init__.py:F405,F403' setup.py retworkx tests rustworkx + run: ruff check rustworkx retworkx setup.py tests - name: Check stray release notes run: python tools/find_stray_release_notes.py - name: rustworkx-core Rust Tests diff --git a/pyproject.toml b/pyproject.toml index 4aee0fecb..4a913c495 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,35 @@ build-backend = "setuptools.build_meta" line-length = 100 target-version = ['py38', 'py39', 'py310', 'py311'] +[tool.ruff] +line-length = 100 +src = ["rustworkx", "setup.py", "retworkx", "tests"] +select = [ + "E", # pycodestyle + "F", # pyflakes + "UP", # pyupgrade + "PYI", # flake8-pyi + "Q", # flake8-quotes +] +target-version = "py38" +exclude = [ + ".venv", + ".git", + ".tox", + ".eggs", + "dist", + "doc", + "build", +] + +[tool.ruff.per-file-ignores] +"rustworkx/__init__.py" = ["F405", "F403"] +"rustworkx/__init__.pyi" = ["F403", "F405", "PYI001"] +"rustworkx/digraph.pyi" = ["F403", "F405", "PYI001"] +"rustworkx/graph.pyi" = ["F403", "F405", "PYI001"] +"rustworkx/iterators.pyi" = ["F403", "F405", "PYI001"] +"rustworkx/rustworkx.pyi" = ["F403", "F405", "PYI001"] + [tool.cibuildwheel] manylinux-x86_64-image = "manylinux2014" manylinux-i686-image = "manylinux2014" diff --git a/rustworkx/digraph.pyi b/rustworkx/digraph.pyi index 13735b5fc..1eb54a083 100644 --- a/rustworkx/digraph.pyi +++ b/rustworkx/digraph.pyi @@ -13,7 +13,7 @@ import numpy as np from .iterators import * from .graph import PyGraph -from typing import Any, Callable, Dict, Generic, TypeVar, Optional, List, Tuple, Sequence +from typing import Any, Callable, Generic, TypeVar, Sequence __all__ = ["PyDiGraph"] @@ -33,36 +33,36 @@ class PyDiGraph(Generic[S, T]): def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... def add_edges_from( self, - obj_list: Sequence[Tuple[int, int, T]], + obj_list: Sequence[tuple[int, int, T]], /, - ) -> List[int]: ... + ) -> list[int]: ... def add_edges_from_no_data( - self: PyDiGraph[S, Optional[T]], obj_list: Sequence[Tuple[int, int]], / - ) -> List[int]: ... + self: PyDiGraph[S, T | None], obj_list: Sequence[tuple[int, int]], / + ) -> list[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: Sequence[S], /) -> NodeIndices: ... def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... - def adj(self, node: int, /) -> Dict[int, T]: ... - def adj_direction(self, node: int, direction: bool, /) -> Dict[int, T]: ... + def adj(self, node: int, /) -> dict[int, T]: ... + def adj_direction(self, node: int, direction: bool, /) -> dict[int, T]: ... def compose( self, other: PyDiGraph[S, T], - node_map: Dict[int, Tuple[int, T]], + node_map: dict[int, tuple[int, T]], /, - node_map_func: Optional[Callable[[S], int]] = ..., - edge_map_func: Optional[Callable[[T], int]] = ..., - ) -> Dict[int, int]: ... + node_map_func: Callable[[S], int] | None = ..., + edge_map_func: Callable[[T], int] | None = ..., + ) -> dict[int, int]: ... def copy(self) -> PyDiGraph[S, T]: ... def edge_index_map(self) -> EdgeIndexMap[T]: ... def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... - def edges(self) -> List[T]: ... + def edges(self) -> list[T]: ... def extend_from_edge_list( - self: PyDiGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / + self: PyDiGraph[S | None, T | None], edge_list: Sequence[tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self: PyDiGraph[Optional[S], T], - edge_list: Sequence[Tuple[int, int, T]], + self: PyDiGraph[S | None, T], + edge_list: Sequence[tuple[int, int, T]], /, ) -> None: ... def find_adjacent_node_by_edge(self, node: int, predicate: Callable[[T], bool], /) -> S: ... @@ -70,11 +70,11 @@ class PyDiGraph(Generic[S, T]): self, obj: Callable[[S], bool], /, - ) -> Optional[int]: ... + ) -> int | None: ... def find_predecessors_by_edge( self, node: int, filter_fn: Callable[[T], bool], / - ) -> List[S]: ... - def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> List[S]: ... + ) -> list[S]: ... + def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> list[S]: ... @staticmethod def from_adjacency_matrix( matrix: np.ndarray, /, null_value: float = ... @@ -83,7 +83,7 @@ class PyDiGraph(Generic[S, T]): def from_complex_adjacency_matrix( matrix: np.ndarray, /, null_value: complex = ... ) -> PyDiGraph[int, complex]: ... - def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> list[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... def has_edge(self, node_a: int, node_b: int, /) -> bool: ... @@ -97,31 +97,31 @@ class PyDiGraph(Generic[S, T]): def merge_nodes(self, u: int, v: int, /) -> None: ... def neighbors(self, node: int, /) -> NodeIndices: ... def node_indexes(self) -> NodeIndices: ... - def nodes(self) -> List[S]: ... + def nodes(self) -> list[S]: ... def num_edges(self) -> int: ... def num_nodes(self) -> int: ... def out_degree(self, node: int, /) -> int: ... def out_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def predecessor_indices(self, node: int, /) -> NodeIndices: ... - def predecessors(self, node: int, /) -> List[S]: ... + def predecessors(self, node: int, /) -> list[S]: ... @staticmethod def read_edge_list( path: str, /, - comment: Optional[str] = ..., - deliminator: Optional[str] = ..., + comment: str | None = ..., + deliminator: str | None = ..., labels: bool = ..., ) -> PyDiGraph: ... def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from(self, index_list: Sequence[Tuple[int, int]], /) -> None: ... + def remove_edges_from(self, index_list: Sequence[tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_node_retain_edges( self, node: int, /, - use_outgoing: Optional[bool] = ..., - condition: Optional[Callable[[S, S], bool]] = ..., + use_outgoing: bool | None = ..., + condition: Callable[[S, S], bool] | None = ..., ) -> None: ... def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... def subgraph(self, nodes: Sequence[int], /, preserve_attrs: bool = ...) -> PyDiGraph[S, T]: ... @@ -129,26 +129,26 @@ class PyDiGraph(Generic[S, T]): self, node: int, other: PyDiGraph[S, T], - edge_map_fn: Callable[[int, int, T], Optional[int]], + edge_map_fn: Callable[[int, int, T], int | None], /, - node_filter: Optional[Callable[[S], bool]] = ..., - edge_weight_map: Optional[Callable[[T], T]] = ..., + node_filter: Callable[[S], bool] | None = ..., + edge_weight_map: Callable[[T], T] | None = ..., ) -> NodeMap: ... def successor_indices(self, node: int, /) -> NodeIndices: ... - def successors(self, node: int, /) -> List[S]: ... + def successors(self, node: int, /) -> list[S]: ... def to_dot( self, /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = ..., - edge_attr: Optional[Callable[[T], Dict[str, str]]] = ..., - graph_attr: Optional[Dict[str, str]] = ..., - filename: Optional[str] = ..., - ) -> Optional[str]: ... + node_attr: Callable[[S], dict[str, str]] | None = ..., + edge_attr: Callable[[T], dict[str, str]] | None = ..., + graph_attr: dict[str, str] | None = ..., + filename: str | None = ..., + ) -> str | None: ... def to_undirected( self, /, multigraph: bool = ..., - weight_combo_fn: Optional[Callable[[T, T], T]] = ..., + weight_combo_fn: Callable[[T, T], T] | None = ..., ) -> PyGraph[S, T]: ... def update_edge( self, @@ -163,8 +163,8 @@ class PyDiGraph(Generic[S, T]): self, path: str, /, - deliminator: Optional[str] = ..., - weight_fn: Optional[Callable[[T], str]] = ..., + deliminator: str | None = ..., + weight_fn: Callable[[T], str] | None = ..., ) -> None: ... def reverse(self) -> None: ... def __delitem__(self, idx: int, /) -> None: ... diff --git a/rustworkx/graph.pyi b/rustworkx/graph.pyi index 44eb37260..e491b4c8f 100644 --- a/rustworkx/graph.pyi +++ b/rustworkx/graph.pyi @@ -15,12 +15,8 @@ from .iterators import * from typing import ( Any, Callable, - Dict, Generic, TypeVar, - Optional, - List, - Tuple, Sequence, ) @@ -35,35 +31,35 @@ class PyGraph(Generic[S, T]): def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... def add_edges_from( self, - obj_list: Sequence[Tuple[int, int, T]], + obj_list: Sequence[tuple[int, int, T]], /, - ) -> List[int]: ... + ) -> list[int]: ... def add_edges_from_no_data( - self: PyGraph[S, Optional[T]], obj_list: Sequence[Tuple[int, int]], / - ) -> List[int]: ... + self: PyGraph[S, T | None], obj_list: Sequence[tuple[int, int]], / + ) -> list[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: Sequence[S], /) -> NodeIndices: ... - def adj(self, node: int, /) -> Dict[int, T]: ... + def adj(self, node: int, /) -> dict[int, T]: ... def compose( self, other: PyGraph[S, T], - node_map: Dict[int, Tuple[int, T]], + node_map: dict[int, tuple[int, T]], /, - node_map_func: Optional[Callable[[S], int]] = ..., - edge_map_func: Optional[Callable[[T], int]] = ..., - ) -> Dict[int, int]: ... + node_map_func: Callable[[S], int] | None = ..., + edge_map_func: Callable[[T], int] | None = ..., + ) -> dict[int, int]: ... def copy(self) -> PyGraph[S, T]: ... def degree(self, node: int, /) -> int: ... def edge_index_map(self) -> EdgeIndexMap[T]: ... def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... - def edges(self) -> List[T]: ... + def edges(self) -> list[T]: ... def extend_from_edge_list( - self: PyGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / + self: PyGraph[S | None, T | None], edge_list: Sequence[tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self: PyGraph[Optional[S], T], - edge_list: Sequence[Tuple[int, int, T]], + self: PyGraph[S | None, T], + edge_list: Sequence[tuple[int, int, T]], /, ) -> None: ... @staticmethod @@ -74,26 +70,26 @@ class PyGraph(Generic[S, T]): def from_complex_adjacency_matrix( matrix: np.ndarray, /, null_value: complex = ... ) -> PyGraph[int, complex]: ... - def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> list[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... def has_edge(self, node_a: int, node_b: int, /) -> bool: ... def neighbors(self, node: int, /) -> NodeIndices: ... def node_indexes(self) -> NodeIndices: ... - def nodes(self) -> List[S]: ... + def nodes(self) -> list[S]: ... def num_edges(self) -> int: ... def num_nodes(self) -> int: ... @staticmethod def read_edge_list( path: str, /, - comment: Optional[str] = ..., - deliminator: Optional[str] = ..., + comment: str | None = ..., + deliminator: str | None = ..., labels: bool = ..., ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from(self, index_list: Sequence[Tuple[int, int]], /) -> None: ... + def remove_edges_from(self, index_list: Sequence[tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... def subgraph(self, nodes: Sequence[int], /, preserve_attrs: bool = ...) -> PyGraph[S, T]: ... @@ -101,19 +97,19 @@ class PyGraph(Generic[S, T]): self, node: int, other: PyGraph[S, T], - edge_map_fn: Callable[[int, int, T], Optional[int]], + edge_map_fn: Callable[[int, int, T], int | None], /, - node_filter: Optional[Callable[[S], bool]] = ..., - edge_weight_map: Optional[Callable[[T], T]] = ..., + node_filter: Callable[[S], bool] | None = ..., + edge_weight_map: Callable[[T], T] | None = ..., ) -> NodeMap: ... def to_dot( self, /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = ..., - edge_attr: Optional[Callable[[T], Dict[str, str]]] = ..., - graph_attr: Optional[Dict[str, str]] = ..., - filename: Optional[str] = ..., - ) -> Optional[str]: ... + node_attr: Callable[[S], dict[str, str]] | None = ..., + edge_attr: Callable[[T], dict[str, str]] | None = ..., + graph_attr: dict[str, str] | None = ..., + filename: str | None = ..., + ) -> str | None: ... def update_edge( self, source: int, @@ -127,8 +123,8 @@ class PyGraph(Generic[S, T]): self, path: str, /, - deliminator: Optional[str] = ..., - weight_fn: Optional[Callable[[T], str]] = ..., + deliminator: str | None = ..., + weight_fn: Callable[[T], str] | None = ..., ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... diff --git a/rustworkx/iterators.pyi b/rustworkx/iterators.pyi index e0d32c2f8..20779aa18 100644 --- a/rustworkx/iterators.pyi +++ b/rustworkx/iterators.pyi @@ -12,18 +12,14 @@ from typing import ( Any, Generic, - List, - Dict, ItemsView, KeysView, ValuesView, Iterator, Mapping, TypeVar, - Tuple, overload, final, - Optional, ) from abc import ABC from collections.abc import Sequence @@ -65,11 +61,10 @@ class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __getitem__(self: Self, index: slice) -> Self: ... def __getstate__(self) -> Any: ... def __hash__(self) -> int: ... - def __str__(self) -> str: ... def __len__(self) -> int: ... def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Sequence[T_co]) -> None: ... - def __array__(self, _dt: Optional[np.dtype] = ...) -> np.ndarray: ... + def __array__(self, _dt: np.dtype | None = ...) -> np.ndarray: ... class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... @@ -81,7 +76,6 @@ class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __getitem__(self, index: S) -> T_co: ... def __getstate__(self) -> Any: ... def __hash__(self) -> int: ... - def __str__(self) -> str: ... def __iter__(self) -> Iterator[S]: ... def __len__(self) -> int: ... def __ne__(self, other: object) -> bool: ... @@ -103,10 +97,10 @@ class AllPairsPathLengthMapping(RustworkxCustomHashMapIter[int, PathLengthMappin class AllPairsPathMapping(RustworkxCustomHashMapIter[int, PathMapping]): ... @final -class BFSSuccessors(Generic[T_co], RustworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... +class BFSSuccessors(Generic[T_co], RustworkxCustomVecIter[tuple[T_co, list[T_co]]]): ... @final -class EdgeIndexMap(Generic[T_co], RustworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... +class EdgeIndexMap(Generic[T_co], RustworkxCustomHashMapIter[int, tuple[int, int, T_co]]): ... @final class EdgeIndices(RustworkxCustomVecIter[int]): ... @@ -115,7 +109,7 @@ class EdgeIndices(RustworkxCustomVecIter[int]): ... class Chains(RustworkxCustomVecIter[EdgeIndices]): ... @final -class EdgeList(RustworkxCustomVecIter[Tuple[int, int]]): ... +class EdgeList(RustworkxCustomVecIter[tuple[int, int]]): ... @final class NodeMap(RustworkxCustomHashMapIter[int, int]): ... @@ -124,22 +118,22 @@ class NodeMap(RustworkxCustomHashMapIter[int, int]): ... class NodesCountMapping(RustworkxCustomHashMapIter[int, int]): ... @final -class Pos2DMapping(RustworkxCustomHashMapIter[int, Tuple[float, float]]): ... +class Pos2DMapping(RustworkxCustomHashMapIter[int, tuple[float, float]]): ... @final -class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[Tuple[int, int, T_co]]): ... +class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[tuple[int, int, T_co]]): ... @final class CentralityMapping(RustworkxCustomHashMapIter[int, float]): ... @final -class BiconnectedComponents(RustworkxCustomHashMapIter[Tuple[int, int], int]): ... +class BiconnectedComponents(RustworkxCustomHashMapIter[tuple[int, int], int]): ... @final -class ProductNodeMap(RustworkxCustomHashMapIter[Tuple[int, int], int]): ... +class ProductNodeMap(RustworkxCustomHashMapIter[tuple[int, int], int]): ... @final -class MultiplePathMapping(RustworkxCustomHashMapIter[int, List[List[int]]]): ... +class MultiplePathMapping(RustworkxCustomHashMapIter[int, list[list[int]]]): ... @final class AllPairsMultiplePathMapping(RustworkxCustomHashMapIter[int, MultiplePathMapping]): ... diff --git a/setup.py b/setup.py index e734d8be1..1a8542a75 100644 --- a/setup.py +++ b/setup.py @@ -18,17 +18,17 @@ def readme(): - with open('README.md') as f: + with open("README.md") as f: return f.read() -mpl_extras = ['matplotlib>=3.0'] -graphviz_extras = ['pillow>=5.4'] +mpl_extras = ["matplotlib>=3.0"] +graphviz_extras = ["pillow>=5.4"] -PKG_NAME = os.getenv('RUSTWORKX_PKG_NAME', "rustworkx") +PKG_NAME = os.getenv("RUSTWORKX_PKG_NAME", "rustworkx") PKG_VERSION = "0.14.0" PKG_PACKAGES = ["rustworkx", "rustworkx.visualization"] -PKG_INSTALL_REQUIRES = ['numpy>=1.16.0'] +PKG_INSTALL_REQUIRES = ["numpy>=1.16.0"] RUST_EXTENSIONS = [RustExtension("rustworkx.rustworkx", "Cargo.toml", binding=Binding.PyO3, debug=rustworkx_debug)] @@ -54,7 +54,7 @@ def readme(): version=PKG_VERSION, description="A python graph library implemented in Rust", long_description=README, - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", author="Matthew Treinish", author_email="mtreinish@kortar.org", license="Apache 2.0", @@ -87,8 +87,8 @@ def readme(): python_requires=">=3.8", install_requires=PKG_INSTALL_REQUIRES, extras_require={ - 'mpl': mpl_extras, - 'graphviz': graphviz_extras, - 'all': mpl_extras + graphviz_extras, + "mpl": mpl_extras, + "graphviz": graphviz_extras, + "all": mpl_extras + graphviz_extras, } ) diff --git a/tests/retworkx_backwards_compat/digraph/test_dot.py b/tests/retworkx_backwards_compat/digraph/test_dot.py index fb2211c43..7f9318908 100644 --- a/tests/retworkx_backwards_compat/digraph/test_dot.py +++ b/tests/retworkx_backwards_compat/digraph/test_dot.py @@ -50,7 +50,7 @@ def test_digraph_to_dot_to_file(self): res = graph.to_dot(lambda node: node, lambda edge: edge, filename=self.path) self.addCleanup(os.remove, self.path) self.assertIsNone(res) - with open(self.path, "r") as fd: + with open(self.path) as fd: res = fd.read() self.assertEqual(expected, res) diff --git a/tests/retworkx_backwards_compat/digraph/test_edgelist.py b/tests/retworkx_backwards_compat/digraph/test_edgelist.py index 45ae47091..83b0d1221 100644 --- a/tests/retworkx_backwards_compat/digraph/test_edgelist.py +++ b/tests/retworkx_backwards_compat/digraph/test_edgelist.py @@ -152,7 +152,7 @@ def test_write_edge_list_empty_digraph(self): graph = retworkx.PyDiGraph() graph.write_edge_list(path) self.addCleanup(os.remove, path) - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual("", edge_file.read()) def test_write_edge_list_round_trip(self): @@ -184,7 +184,7 @@ def test_custom_delim(self): 2,3 3,4 """ - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual(edge_file.read(), expected) def test_invalid_return_type_weight_fn(self): diff --git a/tests/retworkx_backwards_compat/digraph/test_layout.py b/tests/retworkx_backwards_compat/digraph/test_layout.py index 1017f4f91..cb009f013 100644 --- a/tests/retworkx_backwards_compat/digraph/test_layout.py +++ b/tests/retworkx_backwards_compat/digraph/test_layout.py @@ -24,9 +24,8 @@ def assertLayoutEquiv(self, exp, res): rv = res[k] if abs(ev[0] - rv[0]) > self.thres or abs(ev[1] - rv[1]) > self.thres: self.fail( - "The position for node %s, %s, differs from the expected " - "position, %s by more than the allowed threshold of %s" - % (k, rv, ev, self.thres) + f"The position for node {k}, {rv}, differs from the expected " + f"position, {ev} by more than the allowed threshold of {self.thres}" ) diff --git a/tests/retworkx_backwards_compat/graph/test_dot.py b/tests/retworkx_backwards_compat/graph/test_dot.py index fafbbcd87..35c11848a 100644 --- a/tests/retworkx_backwards_compat/graph/test_dot.py +++ b/tests/retworkx_backwards_compat/graph/test_dot.py @@ -104,7 +104,7 @@ def test_graph_to_dot_to_file(self): res = graph.to_dot(lambda node: node, lambda edge: edge, filename=self.path) self.addCleanup(os.remove, self.path) self.assertIsNone(res) - with open(self.path, "r") as fd: + with open(self.path) as fd: res = fd.read() self.assertEqual(expected, res) diff --git a/tests/retworkx_backwards_compat/graph/test_edgelist.py b/tests/retworkx_backwards_compat/graph/test_edgelist.py index c6092a173..a47465fe8 100644 --- a/tests/retworkx_backwards_compat/graph/test_edgelist.py +++ b/tests/retworkx_backwards_compat/graph/test_edgelist.py @@ -148,7 +148,7 @@ def test_write_edge_list_empty_digraph(self): graph = retworkx.PyGraph() graph.write_edge_list(path) self.addCleanup(os.remove, path) - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual("", edge_file.read()) def test_write_edge_list_round_trip(self): @@ -180,7 +180,7 @@ def test_custom_delim(self): 2,3 3,4 """ - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual(edge_file.read(), expected) def test_invalid_return_type_weight_fn(self): diff --git a/tests/retworkx_backwards_compat/graph/test_layout.py b/tests/retworkx_backwards_compat/graph/test_layout.py index 38e56737d..0734df047 100644 --- a/tests/retworkx_backwards_compat/graph/test_layout.py +++ b/tests/retworkx_backwards_compat/graph/test_layout.py @@ -24,9 +24,8 @@ def assertLayoutEquiv(self, exp, res): rv = res[k] if abs(ev[0] - rv[0]) > self.thres or abs(ev[1] - rv[1]) > self.thres: self.fail( - "The position for node %s, %s, differs from the expected " - "position, %s by more than the allowed threshold of %s" - % (k, rv, ev, self.thres) + f"The position for node {k}, {rv}, differs from the expected " + f"position, {ev} by more than the allowed threshold of {self.thres}" ) diff --git a/tests/retworkx_backwards_compat/graph/test_max_weight_matching.py b/tests/retworkx_backwards_compat/graph/test_max_weight_matching.py index 091626da3..cf203143c 100644 --- a/tests/retworkx_backwards_compat/graph/test_max_weight_matching.py +++ b/tests/retworkx_backwards_compat/graph/test_max_weight_matching.py @@ -30,9 +30,9 @@ def compare_match_sets(self, rx_match, expected_match): for (u, v) in rx_match: if (u, v) not in expected_match and (v, u) not in expected_match: self.fail( - "Element %s and it's reverse %s not found in " - "expected output.\nretworkx output: %s\nexpected " - "output: %s" % ((u, v), (v, u), rx_match, expected_match) + f"Element {(u, v)} and it's reverse {(v, u)} not found in " + f"expected output.\nretworkx output: {rx_match}\nexpected " + f"output: {expected_match}" ) def compare_rx_nx_sets(self, rx_graph, rx_matches, nx_matches, seed, nx_graph): @@ -53,11 +53,10 @@ def get_nx_weight(edge): if (u, v) not in nx_matches: if (v, u) not in nx_matches: print( - "seed %s failed. Element %s and it's " - "reverse %s not found in networkx output.\nretworkx" - " output: %s\nnetworkx output: %s\nedge list: %s\n" - "falling back to checking for a valid solution" - % ( + "seed {} failed. Element {} and it's " + "reverse {} not found in networkx output.\nretworkx" + " output: {}\nnetworkx output: {}\nedge list: {}\n" + "falling back to checking for a valid solution".format( seed, (u, v), (v, u), diff --git a/tests/retworkx_backwards_compat/test_custom_return_types.py b/tests/retworkx_backwards_compat/test_custom_return_types.py index a3bb14260..0c6468c7d 100644 --- a/tests/retworkx_backwards_compat/test_custom_return_types.py +++ b/tests/retworkx_backwards_compat/test_custom_return_types.py @@ -1163,7 +1163,7 @@ def test_index_error(self): def test_keys(self): keys = retworkx.all_pairs_dijkstra_path_lengths(self.dag, self.fn).keys() - self.assertEqual([0, 1], list(sorted((keys)))) + self.assertEqual([0, 1], list(sorted(keys))) def test_values(self): values = retworkx.all_pairs_dijkstra_path_lengths(self.dag, self.fn).values() diff --git a/tests/rustworkx_tests/digraph/test_dot.py b/tests/rustworkx_tests/digraph/test_dot.py index 64957ef04..f2dc98428 100644 --- a/tests/rustworkx_tests/digraph/test_dot.py +++ b/tests/rustworkx_tests/digraph/test_dot.py @@ -50,7 +50,7 @@ def test_digraph_to_dot_to_file(self): res = graph.to_dot(lambda node: node, lambda edge: edge, filename=self.path) self.addCleanup(os.remove, self.path) self.assertIsNone(res) - with open(self.path, "r") as fd: + with open(self.path) as fd: res = fd.read() self.assertEqual(expected, res) diff --git a/tests/rustworkx_tests/digraph/test_edgelist.py b/tests/rustworkx_tests/digraph/test_edgelist.py index d47d9f781..d51a08c29 100644 --- a/tests/rustworkx_tests/digraph/test_edgelist.py +++ b/tests/rustworkx_tests/digraph/test_edgelist.py @@ -152,7 +152,7 @@ def test_write_edge_list_empty_digraph(self): graph = rustworkx.PyDiGraph() graph.write_edge_list(path) self.addCleanup(os.remove, path) - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual("", edge_file.read()) def test_write_edge_list_round_trip(self): @@ -184,7 +184,7 @@ def test_custom_delim(self): 2,3 3,4 """ - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual(edge_file.read(), expected) def test_invalid_return_type_weight_fn(self): diff --git a/tests/rustworkx_tests/digraph/test_layout.py b/tests/rustworkx_tests/digraph/test_layout.py index 792557556..5d5b1a0b0 100644 --- a/tests/rustworkx_tests/digraph/test_layout.py +++ b/tests/rustworkx_tests/digraph/test_layout.py @@ -24,9 +24,8 @@ def assertLayoutEquiv(self, exp, res): rv = res[k] if abs(ev[0] - rv[0]) > self.thres or abs(ev[1] - rv[1]) > self.thres: self.fail( - "The position for node %s, %s, differs from the expected " - "position, %s by more than the allowed threshold of %s" - % (k, rv, ev, self.thres) + f"The position for node {k}, {rv}, differs from the expected " + f"position, {ev} by more than the allowed threshold of {self.thres}" ) diff --git a/tests/rustworkx_tests/graph/test_dot.py b/tests/rustworkx_tests/graph/test_dot.py index 5ab04d656..63c98804e 100644 --- a/tests/rustworkx_tests/graph/test_dot.py +++ b/tests/rustworkx_tests/graph/test_dot.py @@ -104,7 +104,7 @@ def test_graph_to_dot_to_file(self): res = graph.to_dot(lambda node: node, lambda edge: edge, filename=self.path) self.addCleanup(os.remove, self.path) self.assertIsNone(res) - with open(self.path, "r") as fd: + with open(self.path) as fd: res = fd.read() self.assertEqual(expected, res) diff --git a/tests/rustworkx_tests/graph/test_edgelist.py b/tests/rustworkx_tests/graph/test_edgelist.py index 95063e54f..6b4165e44 100644 --- a/tests/rustworkx_tests/graph/test_edgelist.py +++ b/tests/rustworkx_tests/graph/test_edgelist.py @@ -148,7 +148,7 @@ def test_write_edge_list_empty_digraph(self): graph = rustworkx.PyGraph() graph.write_edge_list(path) self.addCleanup(os.remove, path) - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual("", edge_file.read()) def test_write_edge_list_round_trip(self): @@ -180,7 +180,7 @@ def test_custom_delim(self): 2,3 3,4 """ - with open(path, "rt") as edge_file: + with open(path) as edge_file: self.assertEqual(edge_file.read(), expected) def test_invalid_return_type_weight_fn(self): diff --git a/tests/rustworkx_tests/graph/test_layout.py b/tests/rustworkx_tests/graph/test_layout.py index 032857899..c656b7fe5 100644 --- a/tests/rustworkx_tests/graph/test_layout.py +++ b/tests/rustworkx_tests/graph/test_layout.py @@ -24,9 +24,8 @@ def assertLayoutEquiv(self, exp, res): rv = res[k] if abs(ev[0] - rv[0]) > self.thres or abs(ev[1] - rv[1]) > self.thres: self.fail( - "The position for node %s, %s, differs from the expected " - "position, %s by more than the allowed threshold of %s" - % (k, rv, ev, self.thres) + f"The position for node {k}, {rv}, differs from the expected " + f"position, {ev} by more than the allowed threshold of {self.thres}" ) diff --git a/tests/rustworkx_tests/graph/test_max_weight_matching.py b/tests/rustworkx_tests/graph/test_max_weight_matching.py index 29e5a3382..429036649 100644 --- a/tests/rustworkx_tests/graph/test_max_weight_matching.py +++ b/tests/rustworkx_tests/graph/test_max_weight_matching.py @@ -30,9 +30,9 @@ def compare_match_sets(self, rx_match, expected_match): for (u, v) in rx_match: if (u, v) not in expected_match and (v, u) not in expected_match: self.fail( - "Element %s and it's reverse %s not found in " - "expected output.\nrustworkx output: %s\nexpected " - "output: %s" % ((u, v), (v, u), rx_match, expected_match) + f"Element {(u, v)} and it's reverse {(v, u)} not found in " + f"expected output.\nrustworkx output: {rx_match}\nexpected " + f"output: {expected_match}" ) def compare_rx_nx_sets(self, rx_graph, rx_matches, nx_matches, seed, nx_graph): @@ -53,11 +53,10 @@ def get_nx_weight(edge): if (u, v) not in nx_matches: if (v, u) not in nx_matches: print( - "seed %s failed. Element %s and it's " - "reverse %s not found in networkx output.\nrustworkx" - " output: %s\nnetworkx output: %s\nedge list: %s\n" - "falling back to checking for a valid solution" - % ( + "seed {} failed. Element {} and it's " + "reverse {} not found in networkx output.\nrustworkx" + " output: {}\nnetworkx output: {}\nedge list: {}\n" + "falling back to checking for a valid solution".format( seed, (u, v), (v, u), diff --git a/tests/rustworkx_tests/graph/test_substitute_node_with_subgraph.py b/tests/rustworkx_tests/graph/test_substitute_node_with_subgraph.py index 2ddd8bf3e..e76f1f56c 100644 --- a/tests/rustworkx_tests/graph/test_substitute_node_with_subgraph.py +++ b/tests/rustworkx_tests/graph/test_substitute_node_with_subgraph.py @@ -34,7 +34,7 @@ def test_single_node(self): def test_node_filter(self): in_graph = rustworkx.generators.complete_graph(5) res = self.graph.substitute_node_with_subgraph( - 0, in_graph, lambda _, __, ___: 2, node_filter=lambda node: node == None + 0, in_graph, lambda _, __, ___: 2, node_filter=lambda node: node is None ) self.assertEqual(res, {i: i + 5 for i in range(5)}) self.assertEqual( diff --git a/tests/rustworkx_tests/test_custom_return_types.py b/tests/rustworkx_tests/test_custom_return_types.py index 2362f125b..48aeb7c0a 100644 --- a/tests/rustworkx_tests/test_custom_return_types.py +++ b/tests/rustworkx_tests/test_custom_return_types.py @@ -1175,7 +1175,7 @@ def test_index_error(self): def test_keys(self): keys = rustworkx.all_pairs_dijkstra_path_lengths(self.dag, self.fn).keys() - self.assertEqual([0, 1], list(sorted((keys)))) + self.assertEqual([0, 1], list(sorted(keys))) def test_values(self): values = rustworkx.all_pairs_dijkstra_path_lengths(self.dag, self.fn).values() diff --git a/tox.ini b/tox.ini index 12f6d1ec8..82ee34eaa 100644 --- a/tox.ini +++ b/tox.ini @@ -33,12 +33,12 @@ commands = basepython = python3 deps = black~=22.0 - flake8 + ruff setuptools-rust whitelist_externals=cargo commands = black --check --diff {posargs} '../rustworkx' '../tests' '../retworkx' - flake8 --per-file-ignores='../rustworkx/__init__.py:F405,F403' ../setup.py ../rustworkx ../retworkx . + ruff check ../rustworkx ../retworkx . ../setup.py cargo fmt --all -- --check python {toxinidir}/tools/find_stray_release_notes.py @@ -77,14 +77,3 @@ basepython = python3 deps = mypy==1.0.1 commands = python -m mypy.stubtest --concise --ignore-missing-stub rustworkx.rustworkx - -[flake8] -# E125 is deliberately excluded. See https://github.com/jcrocholl/pep8/issues/126 -# E123 skipped because it is ignored by default in the default pep8 -# E129 skipped because it is too limiting when combined with other rules -# E711 skipped because sqlalchemy filter() requires using == instead of is -# max-line-length, E203, W503 are added for black compatibility -max-line-length = 110 -ignore = E125,E123,E129,E711 -extend-ignore = E203, W503 -exclude = .venv,.git,.tox,dist,doc,*egg,build