Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dep updates and expansion of ruff CI #351

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,12 @@ jobs:
# run python style checks
- name: Poetry Lock Check
run: poetry check --lock
- name: isort
run: poetry run isort snakebids -c
- name: Black
run: poetry run black snakebids --check
- name: Formatting
run: poetry run ruff format snakebids --check
- name: Linting
run: poetry run ruff check snakebids
- name: pyright
run: poetry run pyright snakebids
- name: ruff
run: poetry run ruff snakebids

build-cache-env:
runs-on: ubuntu-latest
Expand Down
17 changes: 5 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,16 @@ repos:
- id: trailing-whitespace
- repo: local
hooks:
- id: isort
entry: poetry run isort
name: isort
language: system
types_or: [cython, pyi, python]
- repo: local
hooks:
- id: black
entry: poetry run black
name: black
- id: format
entry: poetry run ruff format
name: Ruff Format
language: system
types_or: [cython, pyi, python]
- repo: local
hooks:
- id: system
name: Ruff
entry: poetry run ruff
name: Ruff Lint
entry: poetry run ruff check
language: system
exclude: \._py\}\}$
types_or: [cython, pyi, python]
Expand Down
575 changes: 253 additions & 322 deletions poetry.lock

Large diffs are not rendered by default.

107 changes: 97 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,18 @@ jinja2-time = ">=0.2.0"
requests = ">=2.31.0"

[tool.poetry.group.dev.dependencies]
black = "^23.1.0"
pytest = "^7.0.0"
pytest-mock = "^3.7.0"
isort = "^5.10.1"
poethepoet = "^0.22.0"
poethepoet = "^0.24.0"
pre-commit = "^3.0.0"
mkinit = "^1.0.0"
hypothesis = "^6.34.1"
pytest-benchmark = "^4.0.0"
pyfakefs = "^5.1.0"
pyparsing = "^3.0.9"
pathvalidate = "^3.0.0"
pyright = "==1.1.324"
ruff = "^0.0.290"
pyright = "^1.1.339"
ruff = "^0.1.7"
pytest-xdist = "^3.3.1"
pytest-split = "^0.8.1"
tomli = "^2.0.1"
Expand All @@ -98,13 +96,13 @@ build-backend = "poetry_dynamic_versioning.backend"

[tool.poe.tasks]
setup = "pre-commit install"
quality.shell = "isort snakebids && black snakebids && ruff snakebids && pyright snakebids"
fix.shell = "ruff --fix snakebids && isort snakebids && black snakebids"
quality.shell = "ruff format --check snakebids && ruff check snakebids && pyright snakebids"
fix.shell = "ruff format snakebids && ruff check --fix snakebids"
test = """
pytest --doctest-modules --ignore=docs \
--ignore=snakebids/project_template --benchmark-disable
"""
mkinit = "mkinit --recursive --nomods --black -i snakebids"
mkinit.shell = "mkinit --recursive --nomods -i snakebids && ruff format snakebids && ruff check --fix --select I001 snakebids "
benchmark = "pytest --benchmark-only --benchmark-autosave"

[tool.poe.tasks._get_version]
Expand Down Expand Up @@ -139,11 +137,100 @@ reportImportCycles = false
[tool.ruff]
select = [
"E", # pycodestyle error
"W", # pycodestyle warning
"F", # pyflakes
"N", # pep8-naming
"UP", # pyupgrade
"YTT", # flake8-2020
"S", # flake8-bandit
"BLE", # flake8-blind-except
"B", # flake8-bugbear
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"T10", # flake8-debugger
"EM", # flake8-errmsg
"FA", # flake8-future-annotations
"ISC", # flake8-implicit-str-concat
"ICN", # flake8-import-conventions
"G", # flake8-logging-format
"INP", # flake8-no-pep420
"PIE", # flake8-pie
"PT", # flake8-pytest-style
"RSE", # flake8-raise
"RET", # flake8-return
"SLF", # flake8-self
"SIM", # flake8-simplify
# We use os.path a lot in "legitimate" ways, so this ruleset has too many
# false positives
# "PTH", # flake8-use-pathlib
"TRY", # tryceratops
"FLY", # flynt
"D", # pydocstyle
"PL", # pylint
"RUF", # ruff
"UP", #pyupgrade
"T100", # debugger
"I", # isort
# Other perf rules give more false positives than benefits
"PERF101", # do not cast iterable to list
]
ignore = ["PLR0913"]
ignore = [
"PLR0913",
"D105", # missing docstring in magic method
"D100", # Require docstring in public modules
"D104", # Require docstring in public packages
"S603", # Subprocess without shell equals true
"S607", # start-process-with-partial-path
# recommended ignores for ruff format
"W191",
"E111",
"E114",
"E117",
"D206",
"D300",
"Q000",
"Q001",
"Q002",
"Q003",
"COM812",
"COM819",
"ISC001",
"ISC002",
]


target-version = "py38"

namespace-packages = ["snakebids/plugins"]

[tool.ruff.per-file-ignores]
"snakebids/project_template/**" = ["N999"]
"snakebids/tests/**" = [
"D",
"S101", # assert
"S307", # Use of eval
"SLF",
]

[tool.ruff.pydocstyle]
convention = "numpy"
ignore-decorators = ["snakebids.utils.utils.property_alias"]

[tool.ruff.flake8-builtins]
builtins-ignorelist = ["filter"]

[tool.ruff.flake8-import-conventions.extend-aliases]
itertools = "it"
functools = "ft"
operator = "op"
subprocess = "sp"
importlib_resources = "impr"
"importlib.resources" = "impr"
"importlib.metadata" = "impm"
more_itertools = "itx"
"hypothesis.strategies" = "st"
"snakebids.tests.strategies" = "sb_st"
"snakebids.utils.sb_itertools" = "sb_it"

[tool.ruff.flake8-pytest-style]
fixture-parentheses = false
5 changes: 3 additions & 2 deletions snakebids/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
get_wildcard_constraints,
write_derivative_json,
)
from snakebids.paths import bids
from snakebids.paths import (
bids,
)

__all__ = [
"BidsComponent",
Expand All @@ -35,5 +37,4 @@
"get_wildcard_constraints",
"write_derivative_json",
]

# </AUTOGEN_INIT>
4 changes: 3 additions & 1 deletion snakebids/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@


def create_app(args: argparse.Namespace) -> None:
"""Implement the ``snakebids create`` command."""
output = Path(args.output_dir).resolve()
if not output.parent.exists():
print(
Expand Down Expand Up @@ -47,13 +48,15 @@ def create_app(args: argparse.Namespace) -> None:


def create_descriptor(args: argparse.Namespace) -> None:
"""Implement the ``snakebids boutiques`` command."""
app = SnakeBidsApp(args.app_dir.resolve())
add_dynamic_args(app.parser, app.config["parse_args"], app.config["pybids_inputs"])
app.create_descriptor(args.out_path)
print(f"Boutiques descriptor created at {args.out_path}")


def gen_parser() -> argparse.ArgumentParser:
"""Generate the CLI parser for ``snakebids``."""
parser = argparse.ArgumentParser(
description="Perform administrative Snakebids tasks."
)
Expand Down Expand Up @@ -85,7 +88,6 @@ def gen_parser() -> argparse.ArgumentParser:

def main() -> None:
"""Invoke Snakebids cli."""

parser = gen_parser()
args = parser.parse_args()
args.func(args)
24 changes: 11 additions & 13 deletions snakebids/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import argparse
import logging
import sys
from importlib import metadata
from importlib import metadata as impm
from os import PathLike
from pathlib import Path
from typing import Any, Callable
Expand Down Expand Up @@ -67,9 +67,8 @@ def wrapper(self: SnakeBidsApp):
# else, snakefile
return Path(self.snakemake_dir, path)

raise ConfigError(
f"Error: no {file_name} file found, tried {', '.join(choices)}."
)
msg = f"Error: no {file_name} file found, tried {', '.join(choices)}."
raise ConfigError(msg)

return wrapper

Expand All @@ -85,8 +84,8 @@ def _get_app_version(self: SnakeBidsApp) -> str | None:
SnakeBidsApp's snakemake_dir
"""
try:
return metadata.version(self.snakemake_dir.name)
except metadata.PackageNotFoundError:
return impm.version(self.snakemake_dir.name)
except impm.PackageNotFoundError:
logger.warning(
"App version not found; will be recorded in output as 'unknown'. "
"If this is unexpected, please contact the app maintainer."
Expand Down Expand Up @@ -158,8 +157,7 @@ class SnakeBidsApp:
args: SnakebidsArgs | None = None

def run_snakemake(self) -> None:
"""Run snakemake with the given config, after applying plugins"""

"""Run snakemake with the given config, after applying plugins."""
# If no SnakebidsArgs were provided on class instantiation, we compute args
# using the provided parser
if not self.args:
Expand Down Expand Up @@ -240,8 +238,8 @@ def run_snakemake(self) -> None:
config_file=new_config_file,
data=dict(
app.config,
snakemake_version=metadata.version("snakemake"),
snakebids_version=metadata.version("snakebids"),
snakemake_version=impm.version("snakemake"),
snakebids_version=impm.version("snakebids"),
app_version=app.version or "unknown",
),
force_overwrite=True,
Expand Down Expand Up @@ -286,7 +284,7 @@ def update_config(config: dict[str, Any], snakebids_args: SnakebidsArgs) -> None
# filter_{input_type} dict
pybids_inputs = config["pybids_inputs"]
args = snakebids_args.args_dict
for input_type in pybids_inputs.keys():
for input_type in pybids_inputs:
arg_filter_dict = args[f"filter_{input_type}"]
if arg_filter_dict is not None:
pybids_inputs[input_type].setdefault("filters", {})
Expand All @@ -299,7 +297,7 @@ def update_config(config: dict[str, Any], snakebids_args: SnakebidsArgs) -> None

# add cmdline defined wildcards from the list:
# wildcards_{input_type}
for input_type in pybids_inputs.keys():
for input_type in pybids_inputs:
wildcards_list = args[f"wildcards_{input_type}"]
if wildcards_list is not None:
pybids_inputs[input_type].setdefault("wildcards", [])
Expand All @@ -308,7 +306,7 @@ def update_config(config: dict[str, Any], snakebids_args: SnakebidsArgs) -> None

# add custom input paths to
# config['pybids_inputs'][input_type]['custom_path']
for input_type in pybids_inputs.keys():
for input_type in pybids_inputs:
custom_path = args[f"path_{input_type}"]
if custom_path is not None:
pybids_inputs[input_type]["custom_path"] = Path(custom_path).resolve()
Expand Down
Loading