Skip to content

Commit

Permalink
Pivot to from flake8 to ruff for Python linting (#1006)
Browse files Browse the repository at this point in the history
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

Co-authored-by: Ivan Carvalho <8753214+IvanIsCoding@users.noreply.github.com>
  • Loading branch information
mtreinish and IvanIsCoding authored Oct 16, 2023
1 parent de3eb0c commit b1537d9
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 131 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
29 changes: 29 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
76 changes: 38 additions & 38 deletions rustworkx/digraph.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand All @@ -33,48 +33,48 @@ 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: ...
def find_node_by_weight(
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 = ...
Expand All @@ -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: ...
Expand All @@ -97,58 +97,58 @@ 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]: ...
def substitute_node_with_subgraph(
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,
Expand All @@ -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: ...
Expand Down
60 changes: 28 additions & 32 deletions rustworkx/graph.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ from .iterators import *
from typing import (
Any,
Callable,
Dict,
Generic,
TypeVar,
Optional,
List,
Tuple,
Sequence,
)

Expand All @@ -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
Expand All @@ -74,46 +70,46 @@ 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]: ...
def substitute_node_with_subgraph(
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,
Expand All @@ -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: ...
Expand Down
Loading

0 comments on commit b1537d9

Please sign in to comment.