Skip to content

Commit cdd1f92

Browse files
authored
Merge pull request #1 from effigies/maint/style-and-precommit
chore: Add ruff and pre-commit configurations, apply
2 parents 0a0915a + 52e4d95 commit cdd1f92

File tree

5 files changed

+154
-70
lines changed

5 files changed

+154
-70
lines changed

.pre-commit-config.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.4.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
- id: check-json
9+
- id: check-toml
10+
- id: check-added-large-files
11+
- repo: https://github.com/astral-sh/ruff-pre-commit
12+
rev: v0.4.3
13+
hooks:
14+
- id: ruff
15+
args: [ --fix ]
16+
- id: ruff-format
17+
- id: ruff
18+
args: [ --select, ISC001, --fix ]

pyproject.toml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,47 @@ exclude_lines = [
6767
"if __name__ == .__main__.:",
6868
"if TYPE_CHECKING:",
6969
]
70+
71+
# Disable black
72+
[tool.black]
73+
exclude = ".*"
74+
75+
[tool.ruff]
76+
line-length = 99
77+
extend-exclude = ["_version.py"]
78+
79+
[tool.ruff.lint]
80+
extend-select = [
81+
"F",
82+
"E",
83+
"W",
84+
"I",
85+
"UP",
86+
"YTT",
87+
"S",
88+
"BLE",
89+
"B",
90+
"A",
91+
# "CPY",
92+
"C4",
93+
"DTZ",
94+
"T10",
95+
# "EM",
96+
"EXE",
97+
"ISC",
98+
"ICN",
99+
"PT",
100+
"Q",
101+
]
102+
ignore = [
103+
"ISC001",
104+
]
105+
106+
[tool.ruff.lint.flake8-quotes]
107+
inline-quotes = "single"
108+
109+
[tool.ruff.lint.extend-per-file-ignores]
110+
"*/test_*.py" = ["S101"]
111+
112+
[tool.ruff.format]
113+
quote-style = "single"

src/bids_validator/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""BIDS validator common Python package."""
2+
23
from .bids_validator import BIDSValidator
4+
35
__all__ = ['BIDSValidator']
46

57
from . import _version
8+
69
__version__ = _version.get_versions()['version']

src/bids_validator/bids_validator.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Validation class for BIDS projects."""
2+
23
import logging
34
import os
45
import re
@@ -139,8 +140,10 @@ def parse(cls, path):
139140
path = path.replace(os.sep, '/')
140141

141142
if not path.startswith('/'):
142-
raise ValueError("Path must be relative to root of a BIDS dataset,"
143-
" and must include a leading forward slash `/`.")
143+
raise ValueError(
144+
'Path must be relative to root of a BIDS dataset,'
145+
' and must include a leading forward slash `/`.'
146+
)
144147

145148
for regex in cls.regexes:
146149
match = re.match(regex, path[1:])

src/bids_validator/test_bids_validator.py

Lines changed: 84 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,16 @@
77

88
import os
99

10-
import pytest
1110
import datalad.api
11+
import pytest
1212

1313
from bids_validator import BIDSValidator
1414

1515
HOME = os.path.expanduser('~')
1616

1717
TEST_DATA_DICT = {
18-
'eeg_matchingpennies': (
19-
'https://gin.g-node.org/sappelhoff/eeg_matchingpennies'
20-
),
21-
}
18+
'eeg_matchingpennies': ('https://gin.g-node.org/sappelhoff/eeg_matchingpennies'),
19+
}
2220

2321
EXCLUDE_KEYWORDS = ['git', 'datalad', 'sourcedata', 'bidsignore']
2422

@@ -61,94 +59,112 @@ def test_datasets(validator, fname):
6159
assert validator.is_bids(fname)
6260

6361

64-
@pytest.mark.parametrize('fname, matches', [
65-
('/T1w.json', True),
66-
('/dataset_description.json', True),
67-
('/README', True),
68-
('/CHANGES', True),
69-
('/participants.tsv', True),
70-
('/sub-01/anat/sub-01_T1w.nii.gz', False),
71-
])
62+
@pytest.mark.parametrize(
63+
('fname', 'matches'),
64+
[
65+
('/T1w.json', True),
66+
('/dataset_description.json', True),
67+
('/README', True),
68+
('/CHANGES', True),
69+
('/participants.tsv', True),
70+
('/sub-01/anat/sub-01_T1w.nii.gz', False),
71+
],
72+
)
7273
def test_top_level(validator, fname, matches):
7374
"""Test that is_top_level returns true for top-level files."""
7475
assert validator.is_top_level(fname) is matches
7576

7677

77-
@pytest.mark.parametrize('fname, matches', [
78-
('/sourcedata/unstructured_data.nii.gz', True),
79-
('/sourcedata/dicom_dir/xyz.dcm', True),
80-
('/code/my_analysis/analysis.py', True),
81-
('/derivatives/preproc/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz', True),
82-
('/stimuli/pic.jpg', True),
83-
('/sub-01/anat/sub-01_T1w.nii.gz', False),
84-
])
78+
@pytest.mark.parametrize(
79+
('fname', 'matches'),
80+
[
81+
('/sourcedata/unstructured_data.nii.gz', True),
82+
('/sourcedata/dicom_dir/xyz.dcm', True),
83+
('/code/my_analysis/analysis.py', True),
84+
('/derivatives/preproc/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz', True),
85+
('/stimuli/pic.jpg', True),
86+
('/sub-01/anat/sub-01_T1w.nii.gz', False),
87+
],
88+
)
8589
def test_associated_data(validator, fname, matches):
8690
"""Test that is_associated_data returns true for associated data."""
8791
assert validator.is_associated_data(fname) is matches
8892

8993

90-
@pytest.mark.parametrize('fname, matches', [
91-
('/sub-01/ses-1/sub-01_ses-1_scans.tsv', True),
92-
('/sub-01/ses-1/sub-01_ses-1_scans.json', True),
93-
('/sub-01/sub-01_scans.tsv', True),
94-
('/sub-01/sub-01_scans.json', True),
95-
('/sub-01/ses-1/sub-01_ses-1_task-rest_bold.json', True),
96-
('/sub-01/sub-01_task-rest_bold.json', True),
97-
('/sub-01/ses-1/sub-01_ses-1_asl.json', True),
98-
('/sub-01/sub-01_asl.json', True),
99-
('/sub-01/ses-1/sub-01_ses-1_pet.json', True),
100-
('/sub-01/sub-01_pet.json', True),
101-
('/sub-01/ses-1/sub-01_ses-1_proc-test_channels.tsv', True),
102-
('/sub-01/ses-1/sub-01_ses-1_channels.json', True),
103-
('/sub-01/sub-01_proc-test_channels.tsv', True),
104-
('/sub-01/sub-01_channels.json', True),
105-
('/sub-01/ses-1/sub-01_ses-1_space-CapTrak_electrodes.tsv', True),
106-
('/sub-01/ses-1/sub-01_ses-1_coordsystem.json', True),
107-
('/sub-01/sub-01_space-CapTrak_electrodes.tsv', True),
108-
('/sub-01/sub-01_coordsystem.json', True),
109-
('/sub-01/ses-1/sub-01_ses-1_motion.json', True),
110-
('/sub-01/sub-01_motion.json', True),
111-
('/sub-01/ses-1/sub-01_ses-1_TEM.json', True),
112-
('/sub-01/sub-01_TEM.json', True),
113-
('/sub-01/ses-1/sub-01_ses-1_nirs.json', True),
114-
('/sub-01/sub-01_nirs.json', True),
115-
# Mismatch sessions
116-
('/sub-01/sub-01_ses-1_scans.tsv', False),
117-
('/sub-01/sub-01_ses-1_scans.json', False),
118-
('/sub-01/ses-1/sub-01_ses-2_scans.tsv', False),
119-
# File-level
120-
('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', False),
121-
('/sub-01/anat/sub-01_T1w.nii.gz', False),
122-
])
94+
@pytest.mark.parametrize(
95+
('fname', 'matches'),
96+
[
97+
('/sub-01/ses-1/sub-01_ses-1_scans.tsv', True),
98+
('/sub-01/ses-1/sub-01_ses-1_scans.json', True),
99+
('/sub-01/sub-01_scans.tsv', True),
100+
('/sub-01/sub-01_scans.json', True),
101+
('/sub-01/ses-1/sub-01_ses-1_task-rest_bold.json', True),
102+
('/sub-01/sub-01_task-rest_bold.json', True),
103+
('/sub-01/ses-1/sub-01_ses-1_asl.json', True),
104+
('/sub-01/sub-01_asl.json', True),
105+
('/sub-01/ses-1/sub-01_ses-1_pet.json', True),
106+
('/sub-01/sub-01_pet.json', True),
107+
('/sub-01/ses-1/sub-01_ses-1_proc-test_channels.tsv', True),
108+
('/sub-01/ses-1/sub-01_ses-1_channels.json', True),
109+
('/sub-01/sub-01_proc-test_channels.tsv', True),
110+
('/sub-01/sub-01_channels.json', True),
111+
('/sub-01/ses-1/sub-01_ses-1_space-CapTrak_electrodes.tsv', True),
112+
('/sub-01/ses-1/sub-01_ses-1_coordsystem.json', True),
113+
('/sub-01/sub-01_space-CapTrak_electrodes.tsv', True),
114+
('/sub-01/sub-01_coordsystem.json', True),
115+
('/sub-01/ses-1/sub-01_ses-1_motion.json', True),
116+
('/sub-01/sub-01_motion.json', True),
117+
('/sub-01/ses-1/sub-01_ses-1_TEM.json', True),
118+
('/sub-01/sub-01_TEM.json', True),
119+
('/sub-01/ses-1/sub-01_ses-1_nirs.json', True),
120+
('/sub-01/sub-01_nirs.json', True),
121+
# Mismatch sessions
122+
('/sub-01/sub-01_ses-1_scans.tsv', False),
123+
('/sub-01/sub-01_ses-1_scans.json', False),
124+
('/sub-01/ses-1/sub-01_ses-2_scans.tsv', False),
125+
# File-level
126+
('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', False),
127+
('/sub-01/anat/sub-01_T1w.nii.gz', False),
128+
],
129+
)
123130
def test_session_level(validator, fname, matches):
124131
"""Test that is_session_level returns true for session level files."""
125132
assert validator.is_session_level(fname) is matches
126133

127134

128-
@pytest.mark.parametrize('fname, matches', [
129-
('/sub-01/sub-01_sessions.tsv', True),
130-
('/sub-01/sub-01_sessions.json', True),
131-
('/sub-01/anat/sub-01_T1w.nii.gz', False),
132-
])
135+
@pytest.mark.parametrize(
136+
('fname', 'matches'),
137+
[
138+
('/sub-01/sub-01_sessions.tsv', True),
139+
('/sub-01/sub-01_sessions.json', True),
140+
('/sub-01/anat/sub-01_T1w.nii.gz', False),
141+
],
142+
)
133143
def test_subject_level(validator, fname, matches):
134144
"""Test that is_subject_level returns true for subject level files."""
135145
assert validator.is_subject_level(fname) is matches
136146

137147

138-
@pytest.mark.parametrize('fname, matches', [
139-
('/phenotype/measure.tsv', True),
140-
('/phenotype/measure.json', True),
141-
('/sub-01/anat/sub-01_T1w.nii.gz', False),
142-
])
148+
@pytest.mark.parametrize(
149+
('fname', 'matches'),
150+
[
151+
('/phenotype/measure.tsv', True),
152+
('/phenotype/measure.json', True),
153+
('/sub-01/anat/sub-01_T1w.nii.gz', False),
154+
],
155+
)
143156
def test_phenotpic(validator, fname, matches):
144157
"""Test that is_phenotypic returns true for phenotypic files."""
145158
assert validator.is_phenotypic(fname) is matches
146159

147160

148-
@pytest.mark.parametrize('fname, matches', [
149-
('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', True),
150-
('/sub-01/anat/sub-01_T1w.nii.gz', True),
151-
])
161+
@pytest.mark.parametrize(
162+
('fname', 'matches'),
163+
[
164+
('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', True),
165+
('/sub-01/anat/sub-01_T1w.nii.gz', True),
166+
],
167+
)
152168
def test_file_level(validator, fname, matches):
153169
"""Test that is_file returns true for file level files."""
154170
assert validator.is_file(fname) is matches

0 commit comments

Comments
 (0)