Skip to content

Commit

Permalink
[MAINT] switch to ruff, per napari/napari (#199)
Browse files Browse the repository at this point in the history
Just to make life easier, switching this repo to also use ruff like
napari/napari, instead of flake8 and isort.
Also dropped some old Conda cruft from tox.ini which wasn't used.

After making the tooling changes, I also ran ruff and made various fixes
to get everything to pass.
  • Loading branch information
GenevieveBuckley authored Jan 15, 2024
2 parents fa6ae14 + b2a89ce commit 521d0b3
Show file tree
Hide file tree
Showing 20 changed files with 66 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_and_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
task: [flake8, black, isort]
task: [black, ruff]
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
Expand Down
24 changes: 6 additions & 18 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
repos:
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
exclude: _vendor|vendored|examples
- repo: https://github.com/python/black
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.12.1
hooks:
- id: black
pass_filenames: true
exclude: _vendor|vendored|examples
- repo: https://github.com/PyCQA/flake8
rev: 3.8.4
hooks:
- id: flake8
pass_filenames: true
# this seems to need to be here in addition to setup.cfg
exclude: _vendor|vendored|__init__.py|examples
- repo: https://github.com/asottile/pyupgrade
rev: v2.7.4
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: pyupgrade
args: ["--py37-plus"]
exclude: _vendor|vendored|examples
- id: ruff
args: [ --fix ]
exclude: _vendor|vendored|examples
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,9 @@ You can make sure your `[dev]` installation is working properly by running
`pytest .` from within the repository.

> [!NOTE]
> We use [`pre-commit`](https://pre-commit.com) to sort imports with
> [`isort`](https://github.com/timothycrosley/isort), format code with
> [`black`](https://github.com/psf/black), and lint with
> [`flake8`](https://github.com/PyCQA/flake8) automatically prior to each commit.
> We use [`pre-commit`](https://pre-commit.com) to sort imports and lint with
> [`ruff`](https://github.com/astral-sh/ruff) and format code with
> [`black`](https://github.com/psf/black) automatically prior to each commit.
> To minmize test errors when submitting pull requests, please install `pre-commit`
> in your environment as follows:
> ```sh
Expand Down
2 changes: 2 additions & 0 deletions napari_animation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
from .animation import Animation
from .key_frame import KeyFrame
from .viewer_state import ViewerState

__all__ = ["AnimationWidget", "Animation", "KeyFrame", "ViewerState"]
2 changes: 2 additions & 0 deletions napari_animation/_qt/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .animation_widget import AnimationWidget

__all__ = ["AnimationWidget"]
3 changes: 2 additions & 1 deletion napari_animation/_qt/animation_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
QWidget,
)

from ..animation import Animation
from napari_animation.animation import Animation

from .frame_widget import FrameWidget
from .keyframelistcontrol_widget import KeyFrameListControlWidget
from .keyframeslist_widget import KeyFramesListWidget
Expand Down
4 changes: 2 additions & 2 deletions napari_animation/_qt/savedialog_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ def getAnimationParameters(
self,
parent=None,
caption="Select a file :",
dir=".",
directory=".",
options=None,
):
# Set dialog parameters
self.setWindowTitle(caption)
self.setDirectory(dir)
self.setDirectory(directory)
self.setNameFilter(self._qt_file_name_filters)
self.setFileMode(QFileDialog.AnyFile)
self.setAcceptMode(QFileDialog.AcceptSave)
Expand Down
2 changes: 1 addition & 1 deletion napari_animation/_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def empty_animation(make_napari_viewer):

@pytest.fixture
def animation_with_key_frames(empty_animation):
for i in range(2):
for _i in range(2):
empty_animation.capture_keyframe()
empty_animation.viewer.camera.zoom *= 2
return empty_animation
Expand Down
2 changes: 1 addition & 1 deletion napari_animation/_tests/test_animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def test_animation_file_metadata(animation_with_key_frames, tmp_path, ext):
def test_layer_attribute_capture(layer_state, attribute):
"""Test that 'attribute' is captured in the layer state dictionary"""
for layer_state_dict in layer_state.values():
assert attribute in layer_state_dict.keys()
assert attribute in layer_state_dict


def test_end_state_reached(image_animation):
Expand Down
6 changes: 3 additions & 3 deletions napari_animation/_tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
input_dict = [{"a": 1, "b": {"c": "d"}}]
keys = [["b", "c"]]
expected = ["d"]
test_set = [param for param in zip(input_dict, keys, expected)]
test_set = list(zip(input_dict, keys, expected))


@pytest.mark.parametrize("input_dict,keys,expected", test_set)
Expand All @@ -16,12 +16,12 @@ def test_nested_get(input_dict, keys, expected):

input_dict = [{"a": 1, "b": {"c": "d"}, "e": {}}]
expected = [[["a"], ["b", "c"], ["e"]]]
test_set = [param for param in zip(input_dict, expected)]
test_set = list(zip(input_dict, expected))


@pytest.mark.parametrize("input_dict,expected", test_set)
def test_keys_to_list(input_dict, expected):
result = [keys for keys in keys_to_list(input_dict)]
result = list(keys_to_list(input_dict))
for keys in result:
assert isinstance(keys, list)
assert result == expected
8 changes: 4 additions & 4 deletions napari_animation/animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def animate(
filename,
fps=20,
quality=5,
format=None,
file_format=None,
canvas_only=True,
scale_factor=None,
):
Expand All @@ -158,7 +158,7 @@ def animate(
quality: float
number from 1 (lowest quality) to 9
only applies to non-gif extensions
format: str
file_format: str
The format to use to write the file. By default imageio selects the appropriate
for you based on the filename.
canvas_only : bool
Expand Down Expand Up @@ -202,14 +202,14 @@ def animate(
filename,
fps=fps,
quality=quality,
format=format,
format=file_format,
output_params=output_params,
)
else:
writer = imageio.get_writer(
filename,
duration=duration,
format=format,
format=file_format,
)
except ValueError as err:
print(err)
Expand Down
6 changes: 3 additions & 3 deletions napari_animation/frame_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ def __getitem__(self, key: int) -> ViewerState:
if key not in self._cache:
try:
kf0, kf1, frac = self._keyframe_index[key]
except KeyError:
except KeyError as err:
raise IndexError(
f"Frame index ({key}) out of range ({len(self)} frames)"
)
) from err
if frac == 0:
self._cache[key] = kf0.viewer_state
else:
Expand All @@ -149,7 +149,7 @@ def iter_frames(
scale_factor: float = None,
) -> Iterator[np.ndarray]:
"""Iterate over interpolated viewer states, and yield rendered frames."""
for i, state in enumerate(self):
for _i, state in enumerate(self):
frame = state.render(viewer, canvas_only=canvas_only)
if scale_factor not in (None, 1):
from scipy import ndimage as ndi
Expand Down
2 changes: 2 additions & 0 deletions napari_animation/interpolation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .interpolation_constants import Interpolation
from .typing import InterpolationMap
from .viewer_state_interpolation import interpolate_viewer_state

__all__ = ["Interpolation", "InterpolationMap", "interpolate_viewer_state"]
4 changes: 2 additions & 2 deletions napari_animation/interpolation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ def keys_to_list(input_dict):

def nested_assert_close(a, b):
"""Assert close on nested dicts."""
a_keys = [key for key in keys_to_list(a)]
b_keys = [key for key in keys_to_list(b)]
a_keys = list(keys_to_list(a))
b_keys = list(keys_to_list(b))

assert a_keys == b_keys

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def interpolate_viewer_state(
v0 = nested_get(initial_state, keys)
v1 = nested_get(final_state, keys)

all_keys_are_strings = all([isinstance(key, str) for key in keys])
all_keys_are_strings = all(isinstance(key, str) for key in keys)
if interpolation_map is not None and all_keys_are_strings:
attribute_name = ".".join(keys)
interpolation_function = interpolation_map.get(
Expand Down
2 changes: 1 addition & 1 deletion napari_animation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ def layer_attribute_changed(value, original_value):
return True
return any(
layer_attribute_changed(value[key], original_value[key])
for key in value.keys()
for key in value
)
return not np.array_equal(value, original_value)
5 changes: 2 additions & 3 deletions napari_animation/viewer_state.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
from dataclasses import dataclass

import napari
Expand Down Expand Up @@ -59,10 +60,8 @@ def apply(self, viewer: napari.viewer.Viewer):
# Only setattr if value has changed to avoid expensive redraws
# dicts can hold arrays, e.g. `color`, requiring comparisons of key/value pairs
if layer_attribute_changed(value, original_value):
try:
with contextlib.suppress(AttributeError):
setattr(layer, attribute_name, value)
except AttributeError:
pass

def render(
self, viewer: napari.viewer.Viewer, canvas_only: bool = True
Expand Down
25 changes: 25 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,28 @@ exclude = '''
|
)
'''

# same as napari-cookiecutter
[tool.ruff]
line-length = 79
select = [
"E", "F", "W", #flake8
"UP", # pyupgrade
"I", # isort
"BLE", # flake8-blind-exception
"B", # flake8-bugbear
"A", # flake8-builtins
"C4", # flake8-comprehensions
"ISC", # flake8-implicit-str-concat
"G", # flake8-logging-format
"PIE", # flake8-pie
"SIM", # flake8-simplify
]
ignore = [
"E501", # line too long. let black handle this
"UP006", "UP007", # type annotation. As using magicgui require runtime type annotation then we disable this.
"SIM117", # flake8-simplify - some of merged with statements are not looking great with black, reanble after drop python 3.9
]

target-version = "py38"
fix = true
22 changes: 1 addition & 21 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ testing =
dev =
pre-commit
black
flake8
isort
ruff
check-manifest
%(testing)s

Expand All @@ -60,25 +59,6 @@ napari.manifest =
[options.package_data]
napari-animation = napari.yaml

[isort]
profile = black
line_length = 79
skip_glob = examples/
multi_line_output=3


[flake8]
# Ignores - https://lintlyci.github.io/Flake8Rules
# E203 Whitespace before ':' (sometimes conflicts with black)
# E501 line too long (84 > 79 characters) (sometimes too annoying)
# W503 Line break occurred before a binary operator
# C901 McCabe complexity test. Would be nice to re-enable, but takes work
ignore = E203,W503,E501,C901
max-line-length = 79
max-complexity = 18
exclude = __init__.py,examples


[coverage:report]
exclude_lines =
pragma: no cover
Expand Down
15 changes: 2 additions & 13 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ passenv =
XAUTHORITY
NUMPY_EXPERIMENTAL_ARRAY_FUNCTION
PYVISTA_OFF_SCREEN
conda_deps =
# use conda to install numcodecs on mac py3.9
py39-macos: numcodecs
conda_channels =
conda-forge
deps =
pytest # https://docs.pytest.org/en/latest/contents.html
pytest-cov # https://pytest-cov.readthedocs.io/en/latest/
Expand All @@ -47,16 +42,10 @@ deps =
deps =
napari[pyside2,testing]

[testenv:isort]
[testenv:ruff]
skip_install = True
deps = pre-commit
commands = pre-commit run isort --all-files


[testenv:flake8]
skip_install = True
deps = pre-commit
commands = pre-commit run flake8 --all-files
commands = pre-commit run ruff --all-files


[testenv:black]
Expand Down

0 comments on commit 521d0b3

Please sign in to comment.