Skip to content

Commit 8359479

Browse files
authored
Migrate linting and formatting to Ruff (#236)
* Migrate linting and formatting to Ruff * Prefer future annotations in Ruff checks
1 parent 645aca6 commit 8359479

29 files changed

Lines changed: 264 additions & 170 deletions

‎.github/workflows/main.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
run: uv sync --locked
2424
- name: Run tests
2525
run: uv run --locked pytest
26-
- name: Run pre-commit
26+
- name: Run pre-commit checks
2727
run: uv run --locked pre-commit run --verbose --all-files --show-diff-on-failure
2828
# FIXME: mypy is failing due to missing types-* packages
2929
# - name: Run mypy

‎.pre-commit-config.yaml‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ repos:
1414
additional_dependencies:
1515
- tomli
1616

17-
- repo: https://github.com/psf/black
18-
rev: 23.7.0
19-
hooks:
20-
- id: black
21-
2217
- repo: https://github.com/astral-sh/ruff-pre-commit
23-
rev: v0.0.285
18+
rev: v0.16.6
2419
hooks:
25-
- id: ruff
20+
- id: ruff-check
21+
- id: ruff-format

‎README.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# algorithms-keeper
44
[![CI](https://github.com/TheAlgorithms/algorithms-keeper/actions/workflows/main.yml/badge.svg)](https://github.com/TheAlgorithms/algorithms-keeper/actions/workflows/main.yml)
55
[![codecov](https://codecov.io/gh/TheAlgorithms/algorithms-keeper/branch/master/graph/badge.svg?token=QYAZ665UJL)](https://codecov.io/gh/TheAlgorithms/algorithms-keeper)
6-
[![code style: black](https://img.shields.io/static/v1?label=code%20style&message=black&color=black)](https://github.com/psf/black)
6+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://docs.astral.sh/ruff/)
77
[![Checked with mypy](https://img.shields.io/static/v1?label=mypy&message=checked&color=2a6db2&labelColor=505050)](http://mypy-lang.org/)
88

99
</div>
@@ -57,8 +57,11 @@ the project and run tests from the repository root:
5757
```shell
5858
uv sync
5959
uv run pytest
60+
uv run pre-commit run --all-files
6061
```
6162

63+
Ruff handles Python linting and formatting through the pre-commit hooks.
64+
6265
## Logging
6366
Logging is done using the standard library logging module. All the API calls made by the bot are being logged at INFO level and `aiohttp.log.access_logger` is logging the POST requests made by GitHub for delivering the payload. Other minor events relevant to the repository is also being logged along with using the using [Sentry](https://sentry.io/). The logs can be viewed best using the following command ([_requires Heroku CLI_](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)):
6467
```shell

‎algorithms_keeper/__main__.py‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from __future__ import annotations
2+
13
import asyncio
24
import logging
35
import os
4-
import sys
5-
from datetime import datetime, timezone
6+
from datetime import UTC, datetime
67
from pathlib import Path
7-
from typing import Any, MutableMapping
8+
from typing import TYPE_CHECKING, Any
89

910
from aiohttp import ClientSession, web
1011
from cachetools import LRUCache
@@ -15,10 +16,12 @@
1516
from algorithms_keeper.api import GitHubAPI
1617
from algorithms_keeper.event import main_router
1718

19+
if TYPE_CHECKING:
20+
from collections.abc import MutableMapping
21+
1822
# TODO(dhruvmanila): Remove this block when it's the default.
1923
# https://github.com/Instagram/LibCST/issues/285#issuecomment-1011427731
20-
if sys.version_info >= (3, 10):
21-
os.environ["LIBCST_PARSER_TYPE"] = "native"
24+
os.environ["LIBCST_PARSER_TYPE"] = "native"
2225

2326
cache: MutableMapping[Any, Any] = LRUCache(maxsize=500)
2427

@@ -90,7 +93,7 @@ async def main(request: web.Request) -> web.Response:
9093
logger.info(
9194
"ratelimit=%s, time_remaining=%s",
9295
f"{gh.rate_limit.remaining}/{gh.rate_limit.limit}",
93-
gh.rate_limit.reset_datetime - datetime.now(timezone.utc),
96+
gh.rate_limit.reset_datetime - datetime.now(UTC),
9497
)
9598
return web.Response(status=200)
9699
except Exception as err:
@@ -103,4 +106,4 @@ async def main(request: web.Request) -> web.Response:
103106
app.add_routes(routes)
104107
# Heroku dynamically assigns the app a port, so we can't set the port to a fixed
105108
# number. Heroku adds the port to the env, so we need to pull it from there.
106-
web.run_app(app, port=int(os.environ.get("PORT", 5000)))
109+
web.run_app(app, port=int(os.environ.get("PORT", "5000")))

‎algorithms_keeper/api.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
from __future__ import annotations
2+
13
import logging
24
import os
3-
from typing import Any, Mapping, MutableMapping
5+
from typing import TYPE_CHECKING, Any
46

5-
from aiohttp import ClientResponse
67
from cachetools import TTLCache
78
from gidgethub import apps
89
from gidgethub.abc import UTF_8_CHARSET
910
from gidgethub.aiohttp import GitHubAPI as BaseGitHubAPI
1011

12+
if TYPE_CHECKING:
13+
from collections.abc import Mapping, MutableMapping
14+
15+
from aiohttp import ClientResponse
16+
1117
# Timed token_cache for installation access token (1 minute less than an hour)
1218
token_cache: MutableMapping[int, str] = TTLCache(maxsize=10, ttl=1 * 59 * 60)
1319

‎algorithms_keeper/event/check_run.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
from __future__ import annotations
2+
13
import logging
2-
from typing import Any
4+
from typing import TYPE_CHECKING, Any
35

46
from gidgethub import routing
5-
from gidgethub.sansio import Event
67

78
from algorithms_keeper import utils
8-
from algorithms_keeper.api import GitHubAPI
99
from algorithms_keeper.constants import Label
1010

11+
if TYPE_CHECKING:
12+
from gidgethub.sansio import Event
13+
14+
from algorithms_keeper.api import GitHubAPI
15+
1116
check_run_router = routing.Router()
1217

1318
logger = logging.getLogger(__package__)

‎algorithms_keeper/event/commands.py‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@
55
including the modified files. As we cannot post review comments on lines not part of
66
the diff, this command only modify the labels accordingly.
77
"""
8+
9+
from __future__ import annotations
10+
811
import logging
912
import re
10-
from typing import Any, Pattern
13+
from re import Pattern
14+
from typing import TYPE_CHECKING, Any
1115

1216
from gidgethub import routing
13-
from gidgethub.sansio import Event
1417

1518
from algorithms_keeper import utils
16-
from algorithms_keeper.api import GitHubAPI
1719
from algorithms_keeper.event.pull_request import check_pr_files
1820

21+
if TYPE_CHECKING:
22+
from gidgethub.sansio import Event
23+
24+
from algorithms_keeper.api import GitHubAPI
25+
1926
commands_router = routing.Router()
2027

2128
COMMAND_RE: Pattern[str] = re.compile(r"@algorithms-keeper\s+([a-z\-]+)", re.IGNORECASE)

‎algorithms_keeper/event/installation.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
from __future__ import annotations
2+
13
import logging
2-
from typing import Any
4+
from typing import TYPE_CHECKING, Any
35

46
from gidgethub import routing
5-
from gidgethub.sansio import Event
67

7-
from algorithms_keeper.api import GitHubAPI
88
from algorithms_keeper.constants import GREETING_COMMENT
99

10+
if TYPE_CHECKING:
11+
from gidgethub.sansio import Event
12+
13+
from algorithms_keeper.api import GitHubAPI
14+
1015
installation_router = routing.Router()
1116

1217
logger = logging.getLogger(__package__)

‎algorithms_keeper/event/pull_request.py‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@
1919
"Awaiting changes" -> "Approved" [label="Review approves", color=green]
2020
}
2121
"""
22+
23+
from __future__ import annotations
24+
2225
import asyncio
2326
import logging
2427
import re
25-
from typing import Any, Optional
28+
from typing import TYPE_CHECKING, Any
2629

2730
from gidgethub import routing
28-
from gidgethub.sansio import Event
2931

3032
from algorithms_keeper import utils
31-
from algorithms_keeper.api import GitHubAPI
3233
from algorithms_keeper.constants import (
3334
CHECKBOX_NOT_TICKED_COMMENT,
3435
EMPTY_PR_BODY_COMMENT,
@@ -37,8 +38,14 @@
3738
PR_REVIEW_COMMENT,
3839
Label,
3940
)
41+
from algorithms_keeper.event.check_run import check_ci_status_and_label
4042
from algorithms_keeper.parser import PythonParser
4143

44+
if TYPE_CHECKING:
45+
from gidgethub.sansio import Event
46+
47+
from algorithms_keeper.api import GitHubAPI
48+
4249
# To disable this check, set the constant to 0.
4350
MAX_PR_PER_USER = 3
4451
STAGE_PREFIX = "awaiting"
@@ -50,7 +57,7 @@
5057

5158

5259
async def update_stage_label(
53-
gh: GitHubAPI, *, pull_request: dict[str, Any], next_label: Optional[str] = None
60+
gh: GitHubAPI, *, pull_request: dict[str, Any], next_label: str | None = None
5461
) -> None:
5562
"""Update the stage label of the given pull request.
5663
@@ -266,8 +273,6 @@ async def check_ci_ready_for_review_pr(
266273
removed if the checks are passing or failing. Thus, we need to manually check it
267274
with respect to the latest commit on head.
268275
"""
269-
from algorithms_keeper.event.check_run import check_ci_status_and_label
270-
271276
await check_ci_status_and_label(event, gh, *args, **kwargs)
272277

273278

@@ -343,7 +348,7 @@ async def check_merge_status(
343348
pull_request = event.data["pull_request"]
344349

345350
for retry_interval in range(MAX_RETRIES):
346-
mergeable: Optional[bool] = pull_request["mergeable"]
351+
mergeable: bool | None = pull_request["mergeable"]
347352
if mergeable is None:
348353
# We will use the iter value we get as our sleep period between the polls.
349354
# In the webhook payload, the mergeable status will always be ``None``, so

‎algorithms_keeper/parser/files_parser.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
from __future__ import annotations
2+
13
import logging
2-
from typing import Any, Collection, Iterable, Mapping
4+
from typing import TYPE_CHECKING, Any
35

46
from algorithms_keeper.constants import Label
5-
from algorithms_keeper.utils import File
7+
8+
if TYPE_CHECKING:
9+
from collections.abc import Collection, Iterable, Mapping
10+
11+
from algorithms_keeper.utils import File
612

713
# These files are updated automatically by a GitHub action in almost every pull request.
814
IGNORE_FILES_FOR_TYPELABEL: set[str] = {"DIRECTORY.md"}

0 commit comments

Comments
 (0)