diff --git a/.flake8 b/.flake8 index fd87e09b7..736ce6620 100644 --- a/.flake8 +++ b/.flake8 @@ -1,19 +1,20 @@ [flake8] -ignore= +max_line_length = 88 +extend-ignore= # Whitespace before ':' E203 - # Too many leading '#' for block comment - E266 # Line break occurred before a binary operator W503 # unindexed parameters in the str.format, see: # https://pypi.org/project/flake8-string-format/ P1 - # use `!r` instead of surrounding by quotes - B028 -max_line_length = 88 max-complexity = 10 -select = B,C,E,F,W,T4,B902,T,P,TYP show_source = true count = true min_python_version = 3.8.0 +per-file-ignores = + dvc/testing/benchmarks/conftest.py:F401 + dvc/testing/conftest.py:F401 + dvc/testing/plugin.py:F401 + tests/conftest.py:F401 + tests/func/experiments/executor/test_ssh.py:F401 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd0518508..362bc4824 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,17 +23,6 @@ repos: - id: mixed-line-ending - id: sort-simple-yaml - id: trailing-whitespace - - repo: https://github.com/lovesegfault/beautysh - rev: v6.2.1 - hooks: - - id: beautysh - args: ["-i", "2"] - - repo: https://github.com/asottile/pyupgrade - rev: v3.9.0 - hooks: - - id: pyupgrade - args: - - --py38-plus - repo: https://github.com/psf/black rev: 23.7.0 hooks: @@ -43,7 +32,7 @@ repos: hooks: - id: isort - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.0.278' + rev: 'v0.0.282' hooks: - id: ruff - repo: https://github.com/codespell-project/codespell @@ -52,13 +41,10 @@ repos: - id: codespell additional_dependencies: ["tomli"] - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 additional_dependencies: - - flake8-bugbear - - flake8-comprehensions - - flake8-debugger - flake8-string-format - flake8-typing-imports - repo: https://github.com/PyCQA/bandit diff --git a/dvc/api/data.py b/dvc/api/data.py index a1f9e78c3..d9951b4ce 100644 --- a/dvc/api/data.py +++ b/dvc/api/data.py @@ -67,7 +67,7 @@ class _OpenContextManager(GCM): raise AttributeError("dvc.api.open() should be used in a with statement.") -def open( # noqa, pylint: disable=redefined-builtin +def open( # noqa: A001, pylint: disable=redefined-builtin path: str, repo: Optional[str] = None, rev: Optional[str] = None, diff --git a/dvc/cli/__init__.py b/dvc/cli/__init__.py index 74e457dc6..10ee56902 100644 --- a/dvc/cli/__init__.py +++ b/dvc/cli/__init__.py @@ -230,7 +230,7 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915 logger.exception("") except DvcParserError: ret = 254 - except Exception as exc: # noqa, pylint: disable=broad-except + except Exception as exc: # noqa: BLE001, pylint: disable=broad-except # pylint: disable=no-member ret = _log_exceptions(exc) or 255 diff --git a/dvc/compare.py b/dvc/compare.py index cceb9d7bd..ad57c3268 100644 --- a/dvc/compare.py +++ b/dvc/compare.py @@ -57,7 +57,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]): return self._columns[name] def items(self) -> ItemsView[str, Column]: - projection = {k: self.column(k) for k in self.keys()} # noqa: SIM118 + projection = {k: self.column(k) for k in self.keys()} return projection.items() def keys(self) -> List[str]: @@ -171,8 +171,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]): self.add_column(key) row: List["CellT"] = [ - with_value(d.get(key), self._fill_value) - for key in self.keys() # noqa: SIM118 + with_value(d.get(key), self._fill_value) for key in self.keys() ] self.append(row) @@ -227,7 +226,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]): to_drop -= match_line if axis == "rows": - for name in self.keys(): # noqa: SIM118 + for name in self.keys(): self._columns[name] = Column( [x for n, x in enumerate(self._columns[name]) if n not in to_drop] ) @@ -275,7 +274,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]): else: unique_rows.append(tuple_row) - for name in self.keys(): # noqa: SIM118 + for name in self.keys(): self._columns[name] = Column( [ x diff --git a/dvc/exceptions.py b/dvc/exceptions.py index 5c6b2844d..fd0a0b26e 100644 --- a/dvc/exceptions.py +++ b/dvc/exceptions.py @@ -297,7 +297,7 @@ class URLMissingError(DvcException): super().__init__(f"The path '{url}' does not exist") -class IsADirectoryError(DvcException): # noqa,pylint:disable=redefined-builtin +class IsADirectoryError(DvcException): # noqa: A001,pylint:disable=redefined-builtin """Raised when a file operation is requested on a directory.""" diff --git a/dvc/logger.py b/dvc/logger.py index 2ab0b9311..b49468840 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -160,7 +160,7 @@ class LoggerHandler(logging.StreamHandler): self.flush() except (BrokenPipeError, RecursionError): raise - except Exception: # noqa, pylint: disable=broad-except + except Exception: # noqa: BLE001, pylint: disable=broad-except self.handleError(record) diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index 69475d8b9..33c14b80a 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -497,7 +497,7 @@ class Repo: used_run_cache=None, revs=None, num=1, - push: bool = False, # noqa: F811 + push: bool = False, ): """Get the stages related to the given target and collect the `info` of its outputs. diff --git a/dvc/repo/plots/__init__.py b/dvc/repo/plots/__init__.py index 5d1053455..878df858a 100644 --- a/dvc/repo/plots/__init__.py +++ b/dvc/repo/plots/__init__.py @@ -483,7 +483,7 @@ def _collect_pipeline_files(repo, targets: List[str], props, onerror=None): if isinstance(elem, str): dvcfile_defs_dict[elem] = None else: - k, v = list(elem.items())[0] + k, v = next(iter(elem.items())) dvcfile_defs_dict[k] = v resolved = _resolve_definitions( diff --git a/dvc/repo/worktree.py b/dvc/repo/worktree.py index 6fd86874b..9cf39253b 100644 --- a/dvc/repo/worktree.py +++ b/dvc/repo/worktree.py @@ -427,7 +427,7 @@ def _get_update_diff_index( meta_cmp_key=partial(_meta_checksum, remote.fs), with_unchanged=True, ): - if change.typ == ADD or change.typ == MODIFY: + if change.typ in (ADD, MODIFY): entry = change.new # preserve md5's which were calculated in out.save() after # downloading diff --git a/dvc/scm.py b/dvc/scm.py index fd3239522..945fb33cf 100644 --- a/dvc/scm.py +++ b/dvc/scm.py @@ -67,7 +67,7 @@ def map_scm_exception(with_cause: bool = False) -> Iterator[None]: into = SCMError(str(exc)) if with_cause: raise into from exc - raise into + raise into # noqa: B904 @overload diff --git a/dvc/testing/benchmarks/conftest.py b/dvc/testing/benchmarks/conftest.py index 12c22cdf0..ac47567f7 100644 --- a/dvc/testing/benchmarks/conftest.py +++ b/dvc/testing/benchmarks/conftest.py @@ -1 +1 @@ -from .fixtures import * # noqa, pylint: disable=wildcard-import +from .fixtures import * # noqa: F403 # pylint: disable=wildcard-import diff --git a/dvc/testing/conftest.py b/dvc/testing/conftest.py index 12c22cdf0..6e01dd914 100644 --- a/dvc/testing/conftest.py +++ b/dvc/testing/conftest.py @@ -1 +1 @@ -from .fixtures import * # noqa, pylint: disable=wildcard-import +from .fixtures import * # noqa: F403, pylint: disable=wildcard-import diff --git a/dvc/testing/plugin.py b/dvc/testing/plugin.py index 435f9140c..54c9e468f 100644 --- a/dvc/testing/plugin.py +++ b/dvc/testing/plugin.py @@ -1,5 +1,5 @@ -from .benchmarks.fixtures import * # noqa, pylint: disable=wildcard-import -from .fixtures import * # noqa, pylint: disable=wildcard-import +from .benchmarks.fixtures import * # noqa: F403, pylint: disable=wildcard-import +from .fixtures import * # noqa: F403, pylint: disable=wildcard-import def pytest_generate_tests(metafunc): diff --git a/dvc/utils/serialize/__init__.py b/dvc/utils/serialize/__init__.py index c5f7f9759..5afbab435 100644 --- a/dvc/utils/serialize/__init__.py +++ b/dvc/utils/serialize/__init__.py @@ -1,11 +1,11 @@ from collections import defaultdict from typing import DefaultDict -from ._common import * # noqa, pylint: disable=wildcard-import -from ._json import * # noqa, pylint: disable=wildcard-import -from ._py import * # noqa, pylint: disable=wildcard-import -from ._toml import * # noqa, pylint: disable=wildcard-import -from ._yaml import * # noqa, pylint: disable=wildcard-import +from ._common import * # noqa: F403, pylint: disable=wildcard-import +from ._json import * # noqa: F403, pylint: disable=wildcard-import +from ._py import * # noqa: F403, pylint: disable=wildcard-import +from ._toml import * # noqa: F403, pylint: disable=wildcard-import +from ._yaml import * # noqa: F403, pylint: disable=wildcard-import LOADERS: DefaultDict[str, LoaderFn] = defaultdict( # noqa: F405 lambda: load_yaml # noqa: F405 diff --git a/pyproject.toml b/pyproject.toml index d065fb907..244dd4255 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -300,7 +300,7 @@ ignore-variadic-names = true known-first-party = ["dvc", "dvc_data", "dvc_objects", "dvc_render", "dvc_task", "tests"] [tool.ruff.pep8-naming] -ignore-names = ["M", "SCM"] +extend-ignore-names = ["M", "SCM"] [tool.ruff.per-file-ignores] "dvc/commands/**" = ["N806"] diff --git a/tests/conftest.py b/tests/conftest.py index 19e530baf..1422860cd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,11 +7,11 @@ import pytest from dvc import env from dvc.stage import PipelineStage -from dvc.testing.fixtures import * # noqa, pylint: disable=wildcard-import +from dvc.testing.fixtures import * # noqa: F403, pylint: disable=wildcard-import -from .dir_helpers import * # noqa, pylint: disable=wildcard-import -from .remotes import * # noqa, pylint: disable=wildcard-import -from .scripts import * # noqa, pylint: disable=wildcard-import +from .dir_helpers import * # noqa: F403 # pylint: disable=wildcard-import +from .remotes import * # noqa: F403 # pylint: disable=wildcard-import +from .scripts import * # noqa: F403, pylint: disable=wildcard-import # Prevent updater and analytics from running their processes os.environ["DVC_TEST"] = "true" diff --git a/tests/func/api/test_data.py b/tests/func/api/test_data.py index 09267e8a8..348d7c598 100644 --- a/tests/func/api/test_data.py +++ b/tests/func/api/test_data.py @@ -5,7 +5,7 @@ from funcy import first, get_in from dvc import api from dvc.exceptions import OutputNotFoundError, PathMissingError -from dvc.testing.api_tests import TestAPI # noqa, pylint: disable=unused-import +from dvc.testing.api_tests import TestAPI # noqa: F401, pylint: disable=unused-import from dvc.testing.tmp_dir import make_subrepo from dvc.utils.fs import remove diff --git a/tests/func/experiments/conftest.py b/tests/func/experiments/conftest.py index df4cffb4d..ab478326e 100644 --- a/tests/func/experiments/conftest.py +++ b/tests/func/experiments/conftest.py @@ -1,6 +1,7 @@ import pytest -from tests.unit.repo.experiments.conftest import ( # noqa, pylint disable=unused-argument +# pylint: disable-next=unused-argument +from tests.unit.repo.experiments.conftest import ( # noqa: F401 exp_stage, failed_exp_stage, session_app, diff --git a/tests/func/experiments/executor/test_ssh.py b/tests/func/experiments/executor/test_ssh.py index 7714d1912..7f4ecdd88 100644 --- a/tests/func/experiments/executor/test_ssh.py +++ b/tests/func/experiments/executor/test_ssh.py @@ -10,7 +10,9 @@ from dvc_ssh.tests.cloud import TEST_SSH_KEY_PATH, TEST_SSH_USER from dvc.repo.experiments.executor.base import ExecutorInfo, ExecutorResult from dvc.repo.experiments.executor.ssh import SSHExecutor from dvc.repo.experiments.refs import EXEC_HEAD, EXEC_MERGE -from tests.func.machine.conftest import * # noqa, pylint: disable=wildcard-import + +# pylint: disable-next=wildcard-import +from tests.func.machine.conftest import * # noqa: F403 @contextmanager diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 6154d0eee..e340e6422 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -452,9 +452,9 @@ def temporary_windows_drive(tmp_path_factory): if len(s) > 0 ] - new_drive_name = [ + new_drive_name = next( letter for letter in string.ascii_uppercase if letter not in drives - ][0] + ) new_drive = f"{new_drive_name}:" target_path = tmp_path_factory.mktemp("tmp_windows_drive") diff --git a/tests/func/test_config.py b/tests/func/test_config.py index 5e6e297c9..9829b3ad1 100644 --- a/tests/func/test_config.py +++ b/tests/func/test_config.py @@ -218,7 +218,7 @@ def test_list_bad_args(tmp_dir, dvc, caplog, args): def test_set_invalid_key(dvc): - with pytest.raises(ConfigError, match=r"extra keys not allowed"): # noqa: PT012 + with pytest.raises(ConfigError, match=r"extra keys not allowed"): with dvc.config.edit() as conf: conf["core"]["invalid_key"] = "value" @@ -227,9 +227,7 @@ def test_merging_two_levels(dvc): with dvc.config.edit() as conf: conf["remote"]["test"] = {"url": "ssh://example.com"} - with pytest.raises( # noqa: PT012 - ConfigError, match=r"expected 'url' for dictionary value" - ): + with pytest.raises(ConfigError, match=r"expected 'url' for dictionary value"): with dvc.config.edit("global") as conf: conf["remote"]["test"] = {"password": "1"} diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py index 000d6ab20..ebefe848a 100644 --- a/tests/func/test_data_cloud.py +++ b/tests/func/test_data_cloud.py @@ -10,7 +10,9 @@ from dvc.cli import main from dvc.exceptions import CheckoutError from dvc.repo.open_repo import clean_repos from dvc.stage.exceptions import StageNotFound -from dvc.testing.remote_tests import TestRemote # noqa, pylint: disable=unused-import +from dvc.testing.remote_tests import ( # noqa: F401, pylint: disable=unused-import + TestRemote, +) from dvc.utils.fs import remove from dvc_data.hashfile.db import HashFileDB from dvc_data.hashfile.db.local import LocalHashFileDB diff --git a/tests/func/test_stage.py b/tests/func/test_stage.py index 51814fcfc..c8beb7baf 100644 --- a/tests/func/test_stage.py +++ b/tests/func/test_stage.py @@ -84,7 +84,7 @@ def test_default_wdir_ignored_in_checksum(tmp_dir, dvc): stage = dvc.run(cmd="cp bar foo", deps=["bar"], outs=["foo"], name="copy-foo-bar") d = stage.dumpd() - assert Stage.PARAM_WDIR not in d.keys() + assert Stage.PARAM_WDIR not in d d = load_yaml("dvc.yaml") assert Stage.PARAM_WDIR not in d["stages"]["copy-foo-bar"] @@ -246,13 +246,17 @@ def test_collect_symlink(tmp_dir, dvc, with_deps): with pytest.raises(StageNotFoundError): dvc.stage.collect(target=str(data_link / "foo.dvc"), with_deps=with_deps) else: - stage = list( - dvc.stage.collect(target=str(data_link / "foo.dvc"), with_deps=with_deps) - )[0] + stage = next( + iter( + dvc.stage.collect( + target=str(data_link / "foo.dvc"), with_deps=with_deps + ) + ) + ) assert stage.addressing == os.path.join("data_link", "foo.dvc") - stage = list(dvc.stage.collect(target=f"{foo_path}.dvc", with_deps=with_deps))[0] + stage = next(iter(dvc.stage.collect(target=f"{foo_path}.dvc", with_deps=with_deps))) assert stage.addressing == os.path.join("data", "foo.dvc") diff --git a/tests/remotes/__init__.py b/tests/remotes/__init__.py index 02c1b15ed..c95987efd 100644 --- a/tests/remotes/__init__.py +++ b/tests/remotes/__init__.py @@ -1,4 +1,4 @@ -from dvc_ssh.tests.fixtures import ( # noqa, pylint: disable=unused-import +from dvc_ssh.tests.fixtures import ( # noqa: F401, pylint: disable=unused-import make_ssh, ssh, ssh_server,