Skip to content

Commit 685a807

Browse files
authored
[BE] Add lint workflow (#1557)
And format `smoke_test.py` with `ruff` Invoke/confgure `ruff` using `lintrunner` Copy lint runner adapters from https://github.com/pytorch/pytorch/tree/main/tools/linter/adapters
1 parent 71772d1 commit 685a807

File tree

6 files changed

+629
-8
lines changed

6 files changed

+629
-8
lines changed

.github/workflows/lint.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lintrunner:
15+
name: lintrunner
16+
17+
runs-on: ubuntu-22.04
18+
steps:
19+
- uses: actions/checkout@v3
20+
- name: Setup Python
21+
uses: actions/setup-python@v4
22+
with:
23+
python-version: "3.11"
24+
- name: Install Lintrunner
25+
run: |
26+
pip install lintrunner
27+
lintrunner init
28+
- name: Run lintrunner on all files - Linux
29+
run: |
30+
set +e
31+
if ! lintrunner -v --force-color --all-files --tee-json=lint.json; then
32+
echo ""
33+
echo -e "\e[1m\e[36mYou can reproduce these results locally by using \`lintrunner -m main\`.\e[0m"
34+
exit 1
35+
fi

.lintrunner.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
merge_base_with = "origin/main"
2+
3+
[[linter]]
4+
code = 'RUFF'
5+
include_patterns = ['test/smoke_test/*.py']
6+
command = [
7+
'python3',
8+
'tools/linter/adapters/ruff_linter.py',
9+
'--config=pyproject.toml',
10+
'--show-disable',
11+
'--',
12+
'@{{PATHSFILE}}'
13+
]
14+
init_command = [
15+
'python3',
16+
'tools/linter/adapters/pip_init.py',
17+
'--dry-run={{DRYRUN}}',
18+
'ruff==0.0.290',
19+
]
20+
is_formatter = true

pyproject.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[tool.ruff]
2+
target-version = "py38"
3+
line-length = 120
4+
select = [
5+
"B",
6+
"C4",
7+
"G",
8+
"E",
9+
"F",
10+
"SIM1",
11+
"W",
12+
# Not included in flake8
13+
"UP",
14+
"PERF",
15+
"PGH004",
16+
"PIE807",
17+
"PIE810",
18+
"PLE",
19+
"PLR1722", # use sys exit
20+
"PLW3301", # nested min max
21+
"RUF017",
22+
"TRY302",
23+
]

test/smoke_test/smoke_test.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import os
22
import re
33
import sys
4-
from pathlib import Path
54
import argparse
65
import torch
7-
import platform
86
import importlib
97
import subprocess
108
import torch._dynamo
@@ -41,7 +39,7 @@
4139

4240
class Net(nn.Module):
4341
def __init__(self):
44-
super(Net, self).__init__()
42+
super().__init__()
4543
self.conv1 = nn.Conv2d(1, 32, 3, 1)
4644
self.conv2 = nn.Conv2d(32, 64, 3, 1)
4745
self.fc1 = nn.Linear(9216, 1)
@@ -69,7 +67,7 @@ def check_version(package: str) -> None:
6967

7068

7169
def check_nightly_binaries_date(package: str) -> None:
72-
from datetime import datetime, timedelta
70+
from datetime import datetime
7371
format_dt = '%Y%m%d'
7472

7573
date_t_str = re.findall("dev\\d+", torch.__version__)
@@ -177,11 +175,11 @@ def smoke_test_linalg() -> None:
177175
print("Testing smoke_test_linalg")
178176
A = torch.randn(5, 3)
179177
U, S, Vh = torch.linalg.svd(A, full_matrices=False)
180-
U.shape, S.shape, Vh.shape
178+
assert U.shape == A.shape and S.shape == torch.Size([3]) and Vh.shape == torch.Size([3, 3])
181179
torch.dist(A, U @ torch.diag(S) @ Vh)
182180

183181
U, S, Vh = torch.linalg.svd(A)
184-
U.shape, S.shape, Vh.shape
182+
assert U.shape == A.shape and S.shape == torch.Size([3]) and Vh.shape == torch.Size([3, 3])
185183
torch.dist(A, U[:, :3] @ torch.diag(S) @ Vh)
186184

187185
A = torch.randn(7, 5, 3)
@@ -234,9 +232,9 @@ def smoke_test_modules():
234232
smoke_test_command, stderr=subprocess.STDOUT, shell=True,
235233
universal_newlines=True)
236234
except subprocess.CalledProcessError as exc:
237-
raise RuntimeError(f"Module {module['name']} FAIL: {exc.returncode} Output: {exc.output}")
235+
raise RuntimeError(f"Module {module['name']} FAIL: {exc.returncode} Output: {exc.output}") from exc
238236
else:
239-
print("Output: \n{}\n".format(output))
237+
print(f"Output: \n{output}\n")
240238

241239

242240
def main() -> None:

tools/linter/adapters/pip_init.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
Initializer script that installs stuff to pip.
3+
"""
4+
import argparse
5+
import logging
6+
import os
7+
import subprocess
8+
import sys
9+
import time
10+
11+
from typing import List
12+
13+
14+
def run_command(args: List[str]) -> "subprocess.CompletedProcess[bytes]":
15+
logging.debug("$ %s", " ".join(args))
16+
start_time = time.monotonic()
17+
try:
18+
return subprocess.run(args, check=True)
19+
finally:
20+
end_time = time.monotonic()
21+
logging.debug("took %dms", (end_time - start_time) * 1000)
22+
23+
24+
if __name__ == "__main__":
25+
parser = argparse.ArgumentParser(description="pip initializer")
26+
parser.add_argument(
27+
"packages",
28+
nargs="+",
29+
help="pip packages to install",
30+
)
31+
parser.add_argument(
32+
"--verbose",
33+
action="store_true",
34+
help="verbose logging",
35+
)
36+
parser.add_argument(
37+
"--dry-run", help="do not install anything, just print what would be done."
38+
)
39+
parser.add_argument(
40+
"--no-black-binary",
41+
help="do not use pre-compiled binaries from pip for black.",
42+
action="store_true",
43+
)
44+
45+
args = parser.parse_args()
46+
47+
logging.basicConfig(
48+
format="<%(threadName)s:%(levelname)s> %(message)s",
49+
level=logging.NOTSET if args.verbose else logging.DEBUG,
50+
stream=sys.stderr,
51+
)
52+
53+
pip_args = ["pip3", "install"]
54+
55+
# If we are in a global install, use `--user` to install so that you do not
56+
# need root access in order to initialize linters.
57+
#
58+
# However, `pip install --user` interacts poorly with virtualenvs (see:
59+
# https://bit.ly/3vD4kvl) and conda (see: https://bit.ly/3KG7ZfU). So in
60+
# these cases perform a regular installation.
61+
in_conda = os.environ.get("CONDA_PREFIX") is not None
62+
in_virtualenv = os.environ.get("VIRTUAL_ENV") is not None
63+
if not in_conda and not in_virtualenv:
64+
pip_args.append("--user")
65+
66+
pip_args.extend(args.packages)
67+
68+
for package in args.packages:
69+
package_name, _, version = package.partition("=")
70+
if version == "":
71+
raise RuntimeError(
72+
"Package {package_name} did not have a version specified. "
73+
"Please specify a version to produce a consistent linting experience."
74+
)
75+
if args.no_black_binary and "black" in package_name:
76+
pip_args.append(f"--no-binary={package_name}")
77+
78+
dry_run = args.dry_run == "1"
79+
if dry_run:
80+
print(f"Would have run: {pip_args}")
81+
sys.exit(0)
82+
83+
run_command(pip_args)

0 commit comments

Comments
 (0)