Skip to content

Commit

Permalink
[MAINT]: Add support for ruff linter (#231)
Browse files Browse the repository at this point in the history
* update: add ruff config in pyproject.toml

* chore: remove isort and flake8 configs and envs from tox.ini

* chore: add ruff badge in README

* update: expand target-version for black and cosmetic chages in pyproject.toml

* update: use ruff in lint.yml

* chore: ruff autofixes

* chore: fix ruff N803 issues

* chore: fix ruff C901 issues

* chore: add missing module, function, class and method docstrings

* chore: further ruff fixes and improve typing and docstrings

* chore: ruff F401 checks

* chore: sort imports via ruff

* fix: typo

* chore: add entries in nitpick_ignore_regex in conf.py to build docs

* chore: add changelog 231.misc

* chore: remove unnecessary commands from tox.ini

* fix: E721 issue in test_confounds.py

* Fix codespell

* Add joblib to intersphinx

* Fix some sklearn ignores

* chore: update lint.yml to fix ruff config

* remove this file

---------

Co-authored-by: Fede <[email protected]>
Co-authored-by: Fede Raimondo <[email protected]>
  • Loading branch information
3 people authored Nov 30, 2023
1 parent d691f16 commit fd69745
Show file tree
Hide file tree
Showing 75 changed files with 1,570 additions and 729 deletions.
26 changes: 9 additions & 17 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,18 @@ on:

jobs:
lint:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ['3.11']

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install tox tox-gh-actions
- name: Check with flake8
run: |
tox -e flake8
- name: Check with codespell
run: |
tox -e codespell
python -m pip install --upgrade pip
python -m pip install tox "ruff>=0.1.0"
- name: Run ruff
run: ruff check --output-format=github .
- name: Run codespell
run: tox -e codespell
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ docs/_build/
docs/auto_examples
docs/**/generated
docs/make.bat
docs/sg_execution_times.rst

# PyBuilder
.pybuilder/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
![PyPI - Wheel](https://img.shields.io/pypi/wheel/julearn?style=flat-square)
![GitHub](https://img.shields.io/github/license/juaml/julearn?style=flat-square)
![Codecov](https://img.shields.io/codecov/c/github/juaml/julearn?style=flat-square)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/charliermarsh/ruff)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)

## About
Expand Down
1 change: 1 addition & 0 deletions docs/changes/newsfragments/231.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adopt ``ruff`` as the only linter for the codebase by `Synchon Mandal`_
13 changes: 6 additions & 7 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import re
from sphinx_gallery.sorting import ExplicitOrder
import sys

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))

from pathlib import Path
import sys


# Check if sphinx-multiversion is installed
use_multiversion = False
Expand Down Expand Up @@ -87,6 +85,7 @@
# Sklearn doc issue to be solved in next release
("py:class", "pipeline.Pipeline"),
("py:class", "sklearn.utils.metadata_routing.MetadataRequest"),
("py:class", "julearn.inspect._pipeline.PipelineInspector"),
]


Expand Down Expand Up @@ -157,9 +156,9 @@
"nilearn": ("https://nilearn.github.io/stable/", None),
"nibabel": ("https://nipy.org/nibabel/", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"pandas": ("https://pandas.pydata.org/pandas-docs/dev", None),
# "sqlalchemy": ("https://docs.sqlalchemy.org/en/20/", None),
"joblib": ("https://joblib.readthedocs.io/en/latest/", None),
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
}

Expand Down Expand Up @@ -219,7 +218,7 @@ def __init__(self, src_dir):
self.regex = re.compile(r"^([\w ]+)\n-", re.MULTILINE)

def __repr__(self):
return "<%s>" % (self.__class__.__name__,)
return f"<{self.__class__.__name__}>"

def __call__(self, directory):
src_path = os.path.normpath(os.path.join(self.src_dir, directory))
Expand All @@ -231,7 +230,7 @@ def __call__(self, directory):
readme = os.path.join(src_path, "README.txt")

try:
with open(readme, "r") as f:
with open(readme) as f:
content = f.read()
except FileNotFoundError:
return directory
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Writing Examples
The format used for text is reST. Check the `sphinx RST reference`_ for more
details. The examples are run and displayed in HTML format using
`sphinx gallery`_. To add an example, just create a ``.py`` file that starts
either with ``plot_`` or ``run_``, dependending on whether the example generates
either with ``plot_`` or ``run_``, depending on whether the example generates
a figure or not.

The first lines of the example should be a Python block comment with a title,
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinxext/gh_substitutions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-

from docutils.nodes import reference
from docutils.parsers.rst.roles import set_classes


# Taken from MNE-Python
# adapted from
# https://doughellmann.com/blog/2010/05/09/defining-custom-roles-in-sphinx/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
###############################################################################
# While this plot allows us to see the mean performance values and compare
# them, these samples are paired. In order to see if there is a systematic
# difference, we need to check the distribution of differeces between the
# difference, we need to check the distribution of differences between the
# the models.
#
# First, we remove the column "confounds" from the index and make the difference
Expand Down
1 change: 1 addition & 0 deletions ignore_words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ fpr
master
whis
jupyter
arange
34 changes: 18 additions & 16 deletions julearn/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
# Sami Hamdan <[email protected]>
# License: AGPL

from typing import List, Optional, Union, Dict

from typing import Dict, List, Optional, Union

import numpy as np
import pandas as pd
Expand All @@ -14,26 +13,26 @@
from sklearn.model_selection._search import BaseSearchCV
from sklearn.pipeline import Pipeline

from .inspect import Inspector
from .pipeline import PipelineCreator
from .pipeline.merger import merge_pipelines
from .prepare import check_consistency, prepare_input_data
from .scoring import check_scoring
from .utils import logger, raise_error, _compute_cvmdsum
from .inspect import Inspector
from .utils import _compute_cvmdsum, logger, raise_error


def run_cross_validation(
X: List[str],
def run_cross_validation( # noqa: C901
X: List[str], # noqa: N803
y: str,
model: Union[str, PipelineCreator, BaseEstimator, List[PipelineCreator]],
X_types: Optional[Dict] = None,
X_types: Optional[Dict] = None, # noqa: N803
data: Optional[pd.DataFrame] = None,
problem_type: Optional[str] = None,
preprocess: Union[None, str, List[str]] = None,
return_estimator: Optional[str] = None,
return_inspector: bool = False,
return_train_score: bool = False,
cv: Union[None, int] = None,
cv: Optional[int] = None,
groups: Optional[str] = None,
scoring: Union[str, List[str], None] = None,
pos_labels: Union[str, List[str], None] = None,
Expand All @@ -47,10 +46,10 @@ def run_cross_validation(
Parameters
----------
X : str, list(str) or numpy.array
X : list of str
The features to use.
See :ref:`data_usage` for details.
y : str or numpy.array
y : str
The targets to predict.
See :ref:`data_usage` for details.
model : str or scikit-learn compatible model.
Expand Down Expand Up @@ -106,7 +105,7 @@ def run_cross_validation(
* CV Splitter (see scikit-learn documentation on CV)
* An iterable yielding (train, test) splits as arrays of indices.
groups : str or numpy.array | None
groups : str | None
The grouping labels in case a Group CV is used.
See :ref:`data_usage` for details.
scoring : ScorerLike, optional
Expand Down Expand Up @@ -145,11 +144,16 @@ def run_cross_validation(
seed : int | None
If not None, set the random seed before any operation. Useful for
reproducibility.
n_jobs : int, optional
Number of jobs to run in parallel. Training the estimator and computing
the score are parallelized over the cross-validation splits.
``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
``-1`` means using all processors (default None).
verbose: int
Verbosity level of outer cross-validation.
Follows scikit-learn/joblib converntions.
0 means no additional information is printed.
Larger number genereally mean more information is printed.
Larger number generally mean more information is printed.
Note: verbosity up to 50 will print into standard error,
while larger than 50 will print in standrad output.
Expand Down Expand Up @@ -237,7 +241,7 @@ def run_cross_validation(
else:
model = [model]

problem_types = set([m.problem_type for m in model])
problem_types = {m.problem_type for m in model}
if len(problem_types) > 1:
raise_error(
"If model is a list of PipelineCreator, all elements must have"
Expand Down Expand Up @@ -345,9 +349,7 @@ def run_cross_validation(
check_consistency(y, cv, groups, problem_type)

cv_return_estimator = return_estimator in ["cv", "all"]
scoring = check_scoring(pipeline, scoring,
wrap_score=wrap_score
)
scoring = check_scoring(pipeline, scoring, wrap_score=wrap_score)

cv_mdsum = _compute_cvmdsum(cv_outer)
fit_params = {}
Expand Down
36 changes: 19 additions & 17 deletions julearn/base/column_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def get_column_type(column):
return column.split("__:type:__")[1]


def get_renamer(X_df):
def get_renamer(X_df): # noqa: N803
"""Get the dictionary that will rename the columns to add the type.
Parameters
Expand All @@ -68,26 +68,28 @@ def get_renamer(X_df):
}


class make_type_selector(object):
def __init__(self, pattern):
"""Make a type selector.
class make_type_selector:
"""Make a type selector.
This type selector is to be used with
:class:`sklearn.compose.ColumnTransformer`
This type selector is to be used with
:class:`sklearn.compose.ColumnTransformer`
Parameters
----------
pattern : str
The pattern to select the columns.
Parameters
----------
pattern : str
The pattern to select the columns.
Returns
-------
function
The type selector.
"""
Returns
-------
function
The type selector.
"""

def __init__(self, pattern):
self.pattern = pattern

def __call__(self, X_df):
def __call__(self, X_df): # noqa: N803
"""Select the columns based on the pattern.
Parameters
Expand Down Expand Up @@ -137,7 +139,7 @@ def __init__(self, column_types: ColumnTypesLike):
if isinstance(column_types, ColumnTypes):
_types = column_types._column_types.copy()
elif isinstance(column_types, str):
_types = set([column_types])
_types = {column_types}
elif not isinstance(column_types, Set):
_types = set(column_types)
elif isinstance(column_types, Set):
Expand Down
Loading

0 comments on commit fd69745

Please sign in to comment.